我可以使用:
构造一个数组array ((0,0),(10,10)) [((x,y),(x)) | x<-[0..10], y<-[0..10]]
但是我无法使用函数构造它,甚至不能像以下那样简单:
array ((0,0),(10,10)) [((x,y),f(x)) | x<-[0..10], y<-[0..10]]
这有什么问题?具体来说,如何将“x”转换为Realfrac?
修改 - 没关系,我使用function fromIntegral(num) num
代替function (fromIntegral num) num
。
答案 0 :(得分:3)
索引类型必须属于Ix
类。出于可以理解的原因,没有Double
或Float
等类型的实例。但是你试图乘以Fractional
数字。您必须将索引转换为适当的类型,((x,y), fromIntegral x * 1.5)
应该有效。
答案 1 :(得分:3)
问题在于,当你说(x*1.5)
时,你强迫x
成为一个分数 - 例如Float,Double或Rational - 因为(*)
取两个值相同类型并返回相同类型的值,当然1.5是小数。
问题出现是因为你不能用浮点数来建立一个数组,只有整数,整数元组等等。 1 你可能想要做的是将x
和y
保留为整数,但将转换为小数类型以计算值:
array ((0,0),(10,10)) [((x,y), fromIntegral x * 1.5) | x<-[0..10], y<-[0..10]]
此处x
和y
是整数,但fromIntegral x
是Double。 2 fromIntegral
做的是转换任何积分类型(比如Int,Int64或Integer)到任何Num(在本例中为Double):
fromIntegral :: (Integral a, Num b) => a -> b
最终结果是一个由(Integer, Integer)
索引的数组,其值为Double,这可能是你想要的第一个。 :)
1 具体来说,Ix类型的任何实例都可以;您可以看到完整列表in the documentation。
2 至于为什么选择Integer和Double而不是任何其他Integral或Fractional,这是由于Haskell的默认机制。基本上,如果你的程序中有一个模糊的数字类型,它首先尝试使用Integer,如果这不起作用(例如因为类型必须是Fractional,正如我们已经建立的那样,Integer不是),Double是试过而已。这是相当随意的,但有助于消除歧义,否则它会在很多愚蠢的地方出现。