将`Num`作为`Int`传递给`take`

时间:2014-06-30 02:19:38

标签: haskell

阅读Learn You a Haskell,我正在研究以下内容:

import System.Random

-- We could make a function that generates a finite stream of numbers and a new generator.
finiteRandoms :: (RandomGen g, Random a) => Int -> g -> ([a], g) 
finiteRandoms 0 g = ([], g) 
finiteRandoms n g = let (num, gen) = random g 
                    in (take n $ num : randoms gen, gen)

请注意,上述功能不正确,因为它返回“下一个”gen而不是n

Per LYAH,正确的签名是:

finiteRandoms :: (RandomGen g, Random a, Num n) => n -> g -> ([a], g)

当我尝试take n $ num其中nNum类型时,它无法编译:

Could not deduce (n ~ Int)

鉴于Num,如何将其转换为Int以致电take n

2 个答案:

答案 0 :(得分:13)

一般来说,无法将Num a => a转换为Int。这是因为没有从许多数字类型到整数的规范映射。例如,不可能以1:1的对应关系将复数映射到整数。如果您要将Double转换为Int,则可以使用round,但没有可以为任何数字类型执行此操作的函数。

答案 1 :(得分:10)

如果您想为n使用多态类型,Data.List总是genericTake

genericTake :: Integral i => i -> [a] -> [a]

由于bhkelir指出的原因,你不会像Num那样普遍。