我有一个问题,我认为相当棘手.
标准前奏包含该功能
Run Code Online (Sandbox Code Playgroud)replicate :: Int -> a -> [a]以下看起来似乎是一个合理的定义
Run Code Online (Sandbox Code Playgroud)replicate n x = take n [x,x,..]但实际上这还不够.为什么不?
我知道该replicate函数定义为:
replicate :: Int -> a -> [a]
replicate n x = take n (repeat x)
Run Code Online (Sandbox Code Playgroud)
并repeat定义为:
repeat :: a -> [a]
repeat x = xs where xs = x:xs
Run Code Online (Sandbox Code Playgroud)
定义是否不充分(来自问题),因为它使用无限列表?
首先,问题中存在一个小的语法错误,它应该是:
replicate n x = take n [x,x..]
-- ^ no comma
Run Code Online (Sandbox Code Playgroud)
但是,我们不要挑剔.
现在当你使用范围语法(即x..)时,那么x应该是一个类型的实例Enum.确实:
Prelude> :t \n x -> take n [x,x..]
\n x -> take n [x,x..] :: Enum a => Int -> a -> [a]Run Code Online (Sandbox Code Playgroud)
你可以说x,x..只会生成x,但Haskell编译器在编译时并不知道.
因此,在类型replicate(在这个问题)是太具体:它意味着一种约束- Enum a-这实际上是没有必要的.
另一方面,你自己的定义是完全正确的.Haskell对无限列表没有问题,因为它使用了惰性求值.此外,由于您定义xs与xs作为尾,你真正构建循环链表这也是在内存使用方面更好.