记录类型Haskell中的多态函数

时间:2016-05-03 17:18:34

标签: haskell

我偶然发现了一个我无法在Haskell中解释的行为。我试图在记录类型中存储多态函数,我想在ReaderT Monad中使用它。当我使用asks获取函数时,编译器不会将其识别为多态,并且似乎在函数的第一次出现时修复了该类型。我在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)

尝试运行时,我得到:

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")’

但是,以下代码有效:

runReaderT (ask 
            >>= \(Test f) -> (liftIO . putStrLn $ show (f 2 :: Int))     
                          >> (liftIO . putStrLn $ show (f "hello"))
           ) (Test id)

asks这是特别的吗?我对此提出任何建议表示感谢。

1 个答案:

答案 0 :(得分:4)

上次我查看时,GHC无法推断出更高等级的类型。因此,当你有

\f ->  ... f x .... f y

f永远不会是多态的。

只有两个地方,某些变量的类型是如此明显,以至于类型推断识别出更高级别的类型:在声明更高等级字段的模式中以及在带注释函数的LHS中。

它也应该明确地给出类型,比如

\(f :: forall a.a -> a) -> .... f x ... f y