因此,在学习 Haskell 时,我很快就遇到了可怕的单态限制(在 ghci 中):
Prelude> let f = print.show
Prelude> f 5
<interactive>:3:3:
No instance for (Num ()) arising from the literal `5'
Possible fix: add an instance declaration for (Num ())
In the first argument of `f', namely `5'
In the expression: f 5
In an equation for `it': it = f 5
所以有很多关于这个的材料,例如here,而且解决起来并不难。我可以为 f 添加显式类型签名,也可以关闭单态限制(直接在 ghci 或 .ghci 文件中使用 ":set -XNoMonomorphismRestriction")。
有一些关于单态限制的讨论,但似乎一般建议是可以关闭它(我被告知在较新版本的 ghci 中默认情况下它实际上是关闭的)。
所以我把它关掉了。
但后来我遇到了另一个问题:
Prelude> :set -XNoMonomorphismRestriction
Prelude> let (a,g) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
<interactive>:4:5:
No instance for (System.Random.Random t0)
arising from the ambiguity check for `g'
The type variable `t0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance System.Random.Random Bool -- Defined in `System.Random'
instance System.Random.Random Foreign.C.Types.CChar
-- Defined in `System.Random'
instance System.Random.Random Foreign.C.Types.CDouble
-- Defined in `System.Random'
...plus 33 others
When checking that `g' has the inferred type `System.Random.StdGen'
Probable cause: the inferred type is ambiguous
In the expression:
let (a, g) = System.Random.random (System.Random.mkStdGen 4)
in a :: Int
In an equation for `it':
it
= let (a, g) = System.Random.random (System.Random.mkStdGen 4)
in a :: Int
这实际上是从“Real World Haskell”书中的示例代码简化而来的,这对我不起作用,你可以在这个页面上找到它:http: //book.realworldhaskell.org/read/monads.html(它是Monads 章节和 getRandom 示例函数,在该页面上搜索“getRandom”)。
如果我保留单态限制(或打开它),那么代码就可以工作。如果我将其更改为:它也可以(具有单态限制):
Prelude> let (a,_) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
-106546976
或者如果我之前指定了“a”的类型:
Prelude> let (a::Int,g) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
-106546976
但是,对于第二种解决方法,我必须打开“范围类型变量”扩展(使用“:set -XScopedTypeVariables”)。
问题在于,在这种情况下(单态限制时出现问题),这两种解决方法似乎都不是普遍适用的。
例如,也许我想编写一个函数来做这样的事情并与任意(或多个)类型一起工作,当然在这种情况下,我很可能确实想要保持新的生成器状态(在“g”中) .
那么问题是:我如何解决这种问题,一般来说,而不直接指定确切的类型?
而且,最好(作为 Haskell 新手)更了解这里到底发生了什么,以及为什么会出现这些问题。