我偶然发现了一种我无法用 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
有什么特别之处吗?我很感激对此的任何建议。
最佳答案
上次我检查时,GHC 无法推断出更高级别的类型。因此,当你有
\f -> ... f x .... f y
f
永远不可能是多态的。
只有两个地方某些变量的类型如此明显,以至于类型推断可以识别更高级别的类型:在声明更高级别字段的模式中和在带注释的函数的 LHS 中。
它也应该可以显式地给出类型,如
\(f :: forall a.a -> a) -> .... f x ... f y
关于haskell - 记录类型 Haskell 中的多态函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37010432/