复制的定义不足

时间:2017-05-18 10:01:44

标签: haskell

我有一个问题,我认为相当棘手。

  

标准前奏包含功能

replicate :: Int -> a -> [a]
     

以下看起来似乎是一个合理的定义

replicate n x = take n [x,x,..]
     

但实际上还不够。为什么不呢?

我知道replicate函数定义为:

replicate        :: Int -> a -> [a]       
replicate n x    =  take n (repeat x)

repeat定义为:

repeat           :: a -> [a]  
repeat x         =  xs where xs = x:xs

定义是否不足(来自问题),因为它使用无限列表?

1 个答案:

答案 0 :(得分:5)

首先,问题中存在一个小的语法错误,它应该是:

replicate n x = take n [x,x..]
--                         ^ no comma

但是不要挑剔。

现在,当您使用范围语法(即x..)时,x应该属于Enum的实例。事实上:

Prelude> :t \n x -> take n [x,x..]
\n x -> take n [x,x..] :: Enum a => Int -> a -> [a]

你可以说x,x..只生成x,但Haskell编译器在编译时不知道。

因此replicate(问题中)中的类型太具体:它暗示了类型约束 - Enum a - 实际上不是必要。

另一方面,你自己的定义完全没问题。 Haskell对无限列表没有问题,因为它使用了惰性求值。此外,因为您将xs定义为xs作为尾部,您实际上构建了一个循环链表,在内存使用方面也更好。