【问题标题】:Polymorphic functions in Record Types Haskell记录类型 Haskell 中的多态函数
【发布时间】: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


【解决方案1】:

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

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

f 永远不能是多态的。

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

它也应该明确地给出类型,就像在

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

【讨论】:

  • 感谢您的快速答复!这解释了它。所以匹配 (Test f) -> 是你提到的第一个案例,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
  • 1970-01-01
  • 2018-01-11
  • 2019-10-17
  • 2013-07-19
  • 1970-01-01
相关资源
最近更新 更多