Reputation: 43
i've stumbled upon a behaviour I can't explain in Haskell. I'm trying to store a polymorphic function in a Record Type, which I want to use in a ReaderT Monad. When I get my function with asks
, the compiler doesn't recognize it as polymorphic and seems to fix the type on the first occurance of the function. I created a minimal example of this in ghci:
{-# LANGUAGE Rank2Types #-}
data Test = Test {f :: (forall a. a -> a)}
runReaderT (asks f
>>= \f -> (liftIO . putStrLn $ show (f 2 :: Int))
>> (liftIO . putStrLn $ show (f "hello"))
) (Test id)
When trying to run this, I get:
Couldn't match expected type ‘Int’ with actual type ‘[Char]’
In the first argument of ‘f’, namely ‘"hello"’
In the first argument of ‘show’, namely ‘(f "hello")’
In the second argument of ‘($)’, namely ‘show (f "hello")’
However, following code works:
runReaderT (ask
>>= \(Test f) -> (liftIO . putStrLn $ show (f 2 :: Int))
>> (liftIO . putStrLn $ show (f "hello"))
) (Test id)
So is it something special with asks
? I'm grateful for any advice on this.
Upvotes: 3
Views: 179
Reputation: 36329
Last time I checked, GHC could not infer higher rank types. Thus, when you have
\f -> ... f x .... f y
the f
can never be polymorphic.
There are only two places where the type of some variable is so obvious that type inference recognizes the higher rank type: in patterns that declare higher rank fields and in the LHS of annotated functions.
It also should work to give the type explicitly, like in
\(f :: forall a.a -> a) -> .... f x ... f y
Upvotes: 4