在Haskell中定义函数replic lt
在haskell中定义一个函数replic lt,将lt中的每个元素复制到列表中。如果元素位于lt的第k个位置,则生成的列表包含同一元素的k个副本。必须使用在Haskell中定义函数replic lt,haskell,Haskell,在haskell中定义一个函数replic lt,将lt中的每个元素复制到列表中。如果元素位于lt的第k个位置,则生成的列表包含同一元素的k个副本。必须使用map的高阶函数定义此函数 例如 我的方法很简单,但存在一些问题: maps f [] = [] maps f (x:xs) = f [x] : maps f xs rep a b |b==0 = [] |b<0 = error "negative value" |otherwise = a ++ rep a (b-1)
map
的高阶函数定义此函数
例如
我的方法很简单,但存在一些问题:
maps f [] = []
maps f (x:xs) = f [x] : maps f xs
rep a b
|b==0 = []
|b<0 = error "negative value"
|otherwise = a ++ rep a (b-1)
replicas []=[]
replicas (x:xs) = rep (x:xs) xs
replic (x:xs) = maps replicas (x:xs)
映射f[]=[]
映射f(x:xs)=f[x]:映射f-xs
代表a b
|b==0=[]
|b您可以使用显式递归解决问题,然后尝试检测可以用高阶函数替换递归的某些部分的位置。以下是创建显式递归版本的一些提示:
给replic
一个类型签名和一个基本大小写:
replic :: [a] -> [[a]]
replic [] = ...
replic (x:xs) = ...
如果结果只是[[1],[2],[3],…]
,而不是[[1],[2,2],[3,3],…]
,则可以编写[x]:replic xs
作为递归函数体。但是,您需要创建n个x
副本,但您无权访问任何变量n
。所以你需要引入一个计数器
由于replic
必须接受[a]
并返回[[a]]]
,因此其类型签名中没有计数器的空间,因此您可以创建一个带有额外累积参数的帮助器函数:
replic :: [a] -> [[a]]
replic = replic' 1
replic' :: Int -> [a] -> [[a]]
replic' n [] = ...
replic' n (x:xs) = ...
现在您有了创建n
的x
副本的输入,因此您的rep
功能将派上用场:
rep :: a -> Int -> [a]
rep x n
| n > 0 = x : rep x (n-1)
| otherwise = []
至于用高阶函数来解决这个问题,转换起来有点困难
[ 1, 3, 7, ... ]
[ (1,1), (3,2), (7,3), ... ]
进入
使用map
,因为map
对每个元素执行相同的转换,并且
1 ~> [1]
3 ~> [3,3]
7 ~> [7,7,7]
不是相同转换的产品,因为需要额外的信息(列表中的位置)。使用map
可以做到这一点的唯一方法是将列表中的位置作为要映射的函数输入的一部分。例如,如果您必须转换
[ 1, 3, 7, ... ]
[ (1,1), (3,2), (7,3), ... ]
进入
然后,您可以使用map
和rep
执行此操作
但是您不能使用映射构建此[(1,1)、(3,2)、(7,3),…])
您必须使用显式递归函数或使用(`zip`[1..])
执行此操作
正如其他人所建议的那样,zipWith
结合了map
和zip
到目前为止您尝试了什么?养成为函数提供类型签名的习惯是很好的。您在这里犯了几个错误,我认为如果您已经给出了每个函数的类型签名,您会更容易看到这些错误。尝试为每个映射
、rep
、副本
和replic
提供您认为它们应该具有的签名,并查看由此产生的错误是否解决了您的任何问题。如果您不更新问题中的代码,则无法帮助您解决错误。您肯定没有从那里的代码中得到错误。@user11228628,您为什么建议使用zip
而不是zipWith
?这里显而易见的解决方案是直接应用zipWith
@dfeuer,只是因为OP反复指定必须涉及map
。在第二条评论中,OP表示她知道直接的zipWith
解决方案,但由于它不使用map
,所以不会这样做。
[ (1,1), (3,2), (7,3), ... ]
[ [1], [3,3], [7,7,7], ... ]