我想从0.1
到-150
每隔150
制作一个数字列表。
为此,我创建了一个列表,然后尝试将Fractional multiplication 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
这里发生了什么?为什么当应用于带有map的列表时,Num乘以Fractional的乘法才会失败?
编辑: 我得到的错误是:
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)'
答案 0 :(得分:10)
你发现了“可怕的单态限制”。基本上,GHC会将indices
的类型推断为类似[Integer]
而不是Num a => a
的类型。您可以提供indices :: [Float]
之类的注释,也可以修改定义以避免限制。
例如(不是建议),如果您使indices
成为函数let indices a = [-1500, -1499..1500]
,则推断类型现为(Enum t, Num t) => a -> [t]
。 a
参数未使用但违反了限制。然后,您可以map f (indices whatever)
。请参阅Haskell Wiki中有关Monomorphism Restriction。
答案 1 :(得分: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
答案 2 :(得分:1)
let grid = map (\x -> 0.1 * (fromInteger x)) indices
- 网格[-150.0,-149.9,-149.8,-149.70000000000002,-149.6,-149.5 ......]
答案 3 :(得分:-1)
以下代码为我工作
let indices = [-1500,-1499..1500]
let grid = map ( \x -> x /10 ) indices
它不喜欢0.1
有关完整说明,请参阅此link
上的“单形故障”部分