5

我想列出0.1-150到的每一个数字150

为此,我创建了一个列表,然后尝试将分数乘法 lambda 映射到其上,如下所示:

let indices = [-1500,-1499..1500]
let grid = map (\x -> 0.1 *x) indices

这使得 ghci 吐出一个错误。

另一方面,这两个都可以正常工作:

let a = 0.1*2

let grid = map (\x -> 2 *x) indices

这里发生了什么?为什么仅当应用于带有地图的列表时,Num 乘以小数才会失败?

编辑:我得到的错误是:

No instance for (Fractional Integer)
  arising from the literal `0.1'
Possible fix: add an instance declaration for (Fractional Integer)
In the first argument of `(*)', namely `0.1'
In the expression: 0.1 * x
In the first argument of `map', namely `(\ x -> 0.1 * x)'
4

4 回答 4

10

您已经发现了“可怕的单态限制”。基本上,GHC 会推断出的类型indices是单型,[Integer]而不是Num a => a. 您可以提供类似的注释indices :: [Float],也可以修改定义以避免限制。

例如(不是建议),如果你做indices一个函数:let indices a = [-1500, -1499..1500],推断的类型是 now (Enum t, Num t) => a -> [t]。该a参数未使用,但违反了限制。然后你就可以做到了map f (indices whatever)在 Haskell Wiki 中查看有关Monomorphism Restriction的更多信息。

于 2013-04-04T06:05:39.400 回答
8

这是默认的。

您的indices变量Num默认为 Integer,而不是您可能期望的类型类的多态,此时您不能将其乘以0.1,因为0.1它将解析为某些 Fractional 类型。

您可以使用显式类型签名强制索引是多态的:

let indices :: (Enum a, Num a) => [a]; indices = [-1500,-1499..1500]

尽管在实践中,您通常不希望以这种方式显式地多态列表。

haskell wiki上有一个关于单态限制的页面,虽然它不是特别简洁:http ://www.haskell.org/haskellwiki/Monomorphism_restriction

于 2013-04-04T06:07:35.410 回答
1
let grid = map (\x -> 0.1 * (fromInteger x)) indices

-- 网格 [-150.0,-149.9,-149.8,-149.70000000000002,-149.6,-149.5 ...]

于 2013-04-04T09:06:25.747 回答
-1

以下代码对我有用

let indices = [-1500,-1499..1500]

let grid = map ( \x -> x /10 ) indices

它不喜欢 0.1

有关完整说明,请参阅此链接上的“单态故障”部分

于 2013-04-04T06:00:18.563 回答