函数的Haskell类型推断

Sky*_*ter 8 haskell functor monomorphism-restriction

最近我一直在玩Haskell,特别是整个仿函数概念.我越深入其中,我得到的时刻越多,它肯定会让我的多巴胺受体相当多.

我坚持的问题如下.这是有效的代码,它提升了函数,然后首先将其应用于IO值,然后应用于List.

replicator1 =
  fmap (replicate 3)

replicator2 =
  fmap (replicate 3)

main = do
  replicated <- replicator1 getLine
  print (replicator2 replicated)
Run Code Online (Sandbox Code Playgroud)

以更简洁的方式编写它是非常诱人的,即:

replicator =
  fmap (replicate 3)

main = do
  replicated <- replicator getLine
  print (replicator replicated)
Run Code Online (Sandbox Code Playgroud)

我的一部分说它在概念上是正确的,因为replicator它既可以应用于IO也可以应用于List实例,但是作为强类型语言Haskell不允许我这样做.我想我非常明白为什么会这样.

问题是:有什么方法可以让我更接近后一种变体?或者和前者住在一起好吗?

谢谢!

Tik*_*vis 19

你的代码实际上很好,除了你遇到了可怕的单态限制,这使得Haskell无法推断出最常见的类型replicator.

本质上,受限制,Haskell不会推断出看起来像函数的绑定的多态类型.这意味着如果你尝试在两个不同的上下文中使用它,它必须选择一个类似[]IO为的具体仿函数replicate并导致错误.

您可以通过三种方式使代码工作:

第三种选择是最惯用的.良好的Haskell样式涉及向所有顶级标识符添加显式类型签名.但是,了解其他两个选项以了解正在发生的事情以及能够在Haskell中编写快速和脏的一次性脚本而不用担心类型签名是很有用的.

  • 呃,我感觉更多的多巴胺流动.这是一个惊人的答案!谢谢! (2认同)