【发布时间】:2016-05-04 01:45:01
【问题描述】:
我偶然发现了一种在 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 有什么特别之处吗?我很感谢您对此提出任何建议。
【问题讨论】:
-
我猜这与出现在 \ 之后的
f有关,如果我没记错的话,除非您另有说明,否则 lambda 参数仍然是单态的。 -
请注意:Rank2Types 是一个过时的扩展,别名为 RankNTypes。 (而 RankNTypes 只允许您编写
foralls。在 GHC 中没有更高级别的类型推断,正如 Ingo 的答案细节。)
标签: haskell