SimonJ
SimonJ

Reputation: 43

Polymorphic functions in Record Types Haskell

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

Answers (1)

Ingo
Ingo

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

Related Questions