문제

How does it come, that the following type checks

{-# LANGUAGE RankNTypes #-}
module Main where

class Foo a where


type FunFoo = (Foo a) => a -> IO ()

data Bar = Bar {
  funFoo :: FunFoo
}

setFunFoo :: FunFoo -> Bar -> Bar
setFunFoo action bar = bar {funFoo = action}

but when changing the type signature off setFunFoo to

setFunFoo :: ((Foo a) => a -> IO ()) -> Bar -> Bar

it does not? Is there a way to express the above code without the type synonym FunFoo?

도움이 되었습니까?

해결책

You need to add an explicit forall like so:

setFunFoo :: (forall a. (Foo a) => a -> IO ()) -> Bar -> Bar

The reason for this is because you want the scope of the type variable a to be limited to the type of the first argument to setFunFoo. Without the explicit forall, the desugared type is this:

setFunFoo :: forall a. ((Foo a) => a -> IO ()) -> Bar -> Bar
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top