haskell - 记录类型 Haskell 中的多态函数

标签 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有什么特别之处吗?我很感激对此的任何建议。

最佳答案

上次我检查时,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/

相关文章:

haskell - Haskell 中 pretty-print 表达式结构?

haskell - (Monad m, Monoid o) => m o? 的应用实例

haskell - 异构列表的显示实例

haskell - 反转haskell中的列表

haskell - 在 Haskell 中应用多个参数的更简单方法

list - 如何连接两个 Snoc 列表?

haskell - 访问泛型中的记录名称和函数

list - 如何使用随机选择对 Haskell 中的列表进行洗牌

haskell - 如何用一元函数组成一个二元函数?

haskell - 这个语句中的类型是如何解析的