问题 函数名称的别名具有不同的类型签名。为什么?


import Data.List (genericLength)

len = genericLength

:t genericLength
genericLength :: (Num i) => [b] -> i
:t len
len :: [b] -> Integer

为什么是这种类型 len 不同于 genericLength?这里的目的是使用更短的别名 genericLength

haskell中的功能不是一流的吗?不应该为功能结果赋予相同功能的其他名称吗?


11128
2018-06-12 04:45


起源

我不太了解这个发表答案,但我很确定这与这个问题有关 单态约束。如果你放 {-# LANGUAGE NoMonomorphismRestriction #-} 在文件的顶部,它将按照您期望的方式运行。 - Jeff Burka
杰弗里+1表示它与单态限制有关。 - Babu Srinivasan


答案:


你在这里看到的是因为要求顶级声明 没有争论 是 单态。你可以找到 在Haskell wiki上讨论了这个原因,以及一些有关的信息 控制这种行为 在GHC用户指南中。

如图所示,请注意给予 len 一个参数解决了这个问题:

len x = genericLength x

> :t len
len :: Num i => [b] -> i

给它一个类型签名也是如此:

len :: (Num b) => [a] -> b
len = genericLength

关闭单态限制也是如此:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.List (genericLength)

len = genericLength

> :t len
len :: Num i => [b] -> i

在这个特定的情况下,我认为你也得到了一个不同的类型(而不是编译器错误),因为 违约 指定某些类型类应默认为特定类型的规则(在本例中, Num 默认为 Integer。如果你尝试做同样的事情 fmap 你得到这个:

> :r
[1 of 1] Compiling Main             ( MonoTest.hs, interpreted )

MonoTest.hs:4:5:
    Ambiguous type variable `f0' in the constraint:
      (Functor f0) arising from a use of `fmap'
    Possible cause: the monomorphism restriction applied to the following:
      f :: forall a b. (a -> b) -> f0 a -> f0 b
        (bound at MonoTest.hs:4:1)
    Probable fix: give these definition(s) an explicit type signature
                  or use -XNoMonomorphismRestriction
    In the expression: fmap
    In an equation for `f': f = fmap
Failed, modules loaded: none.

你可以找到一些关于默认的信息 Haskell 98报告。我还要提到GHC支持一种扩展形式的默认,它主要用于GHCi(并默认在那里启用),这偶尔会让人感到困惑。


12
2018-06-12 05:00



谢谢,想知道同样的fI = fromIntegral。 - gorlum0
@ gorlum0:哈哈哈哈,单态和默认肯定会成功 特别 无益的。 - C. A. McCann
请注意,GHC 7.8不应再发生“GHCi中的单态限制现在默认关闭”。 (downloads.haskell.org/~ghc/7.8.1-rc1/docs/html/users_guide/...) - thoferon