Haskell 列表内部列表上的递归
我有一些这样的代码:Haskell 列表内部列表上的递归,haskell,Haskell,我有一些这样的代码: data Set=Set字符串[Int] 派生(显示、阅读) getArr::Set->[Int] getArr(Set_uarr)=arr 我的目标是编写一个将值列表输入元组的函数。 如: 资料-- “一”[1]、“二”[2]、“三”[3] 输出:“一”[0,1],“二”[1,2],“三”[3,3],输入为[0,1,3] 我对此的一般做法是递归地逐个检查数据,同时使用:将其添加到第一个索引中 我试图做一些类似的事情: addToSet::[Set]->[Int]->[
data Set=Set字符串[Int]
派生(显示、阅读)
getArr::Set->[Int]
getArr(Set_uarr)=arr
我的目标是编写一个将值列表输入元组的函数。
如:
资料--
“一”[1]、“二”[2]、“三”[3]
输出:“一”[0,1],“二”[1,2],“三”[3,3]
,输入为[0,1,3]
我对此的一般做法是递归地逐个检查数据,同时使用:将其添加到第一个索引中
我试图做一些类似的事情:
addToSet::[Set]->[Int]->[Set]
addToSet[][]=[]
addToSet(x:xs)(y:ys)=(getArr x:y)++addToSet-xs
但我得到一个错误,说:
Couldn't match type ‘[Int]’ with ‘Set’
Expected type: [Set]
Actual type: [[Int]]```
考虑helper函数
updateSet :: Set -> Int -> Set
updateSet (Set s xs) y = Set s (y:xs)
这只是将单个值添加到给定集:
>>> updateSet (Set "One" [1]) 0
Set "One" [0,1]
然后,addToSet
只是zipWith的一个包装:
addToSet :: [Set] -> [Int] -> [Set]
addToSet = zipWith updateSet
updateSet
对第一个集合和第一个整数调用,然后对第二个集合和第二个整数调用,依此类推,结果按顺序组合在一个列表中
另一种方法是将(Set,Int)->Int类型的函数映射到将两个列表压缩在一起的结果上:
updateSet' :: (Set, Int) -> Set
updateSet' (Set s xs, y) -> Set s (y:xs)
addToSet :: [Set] -> [Int] -> [Set]
addToSet ss is = map updateSet' (zip ss is)
请注意,updateSet'=uncurry updateSet
请考虑helper函数
updateSet :: Set -> Int -> Set
updateSet (Set s xs) y = Set s (y:xs)
这只是将单个值添加到给定集:
>>> updateSet (Set "One" [1]) 0
Set "One" [0,1]
然后,addToSet
只是zipWith的一个包装:
addToSet :: [Set] -> [Int] -> [Set]
addToSet = zipWith updateSet
updateSet
对第一个集合和第一个整数调用,然后对第二个集合和第二个整数调用,依此类推,结果按顺序组合在一个列表中
另一种方法是将(Set,Int)->Int类型的函数映射到将两个列表压缩在一起的结果上:
updateSet' :: (Set, Int) -> Set
updateSet' (Set s xs, y) -> Set s (y:xs)
addToSet :: [Set] -> [Int] -> [Set]
addToSet ss is = map updateSet' (zip ss is)
请注意,updateSet'=uncurry updateSet
这里发生了很多事情-首先get Arr x:y
会导致Int
-列表(getArr的结果)被预先加在一个[Int]`(y
)-然后该列表的结果(不管它是什么)被连接到一个[Int]>[Set]
(您仅将xs
部分应用于addToSet
)。。。另外:您能举一个更好的例子(输入到addToSet
和预期输出)吗?你在上半部分的例子似乎与下半部分完全没有关联,这里发生了很多事情-第一个get Arr x:y
将导致一个Int
-列表(getArr
的结果)被前置到一个[Int]`(y
)-然后是结果(不管它是什么)与[Int]->[Set]
连接(您仅将xs
部分应用于addToSet
)。。。另外:您能举一个更好的例子(输入到addToSet
和预期输出)吗?你上半部分的例子似乎与下半部分没有任何关联。我理解你的解释,并对此表示感谢,但我尝试运行了addToSet(sampleSet[0,1,3])
,但我发现一个错误括号用错了。调用只需addToSet sampleSet[0,1,3]
。具体来说,函数调用中不使用括号,除非将子表达式定义为单个参数。函数调用本身就是用空格分隔的函数及其参数。请注意,fooxy
是两个函数调用:foox
返回一个函数,然后将该函数应用于y
。非正式地说,你可以把它看作是对foo
的一次调用,使用两个参数。我有时想知道,我们是否在使用“函数应用程序是并置的”行时对新的Haskeller造成了伤害。也许像其他语言一样,教他们“所有函数都接受一个参数”和“使用parens进行应用”会更好。所以foo(x)(y)(z)
因为我们将foo
应用于x
,然后将foo(x)
应用于y
,然后将foo(x)(y)
应用于z
。然后在以后的某个日期,我们可以告诉他们,作为一种标记方便,您可以在单个令牌或其他东西周围放置paren。。。但我相信会有一些新的困惑,这是目前的方式所没有的。唉,Haskell只是使用了更高层次的抽象map
和zip
基本上通过表示非常常用的模式来“隐藏”递归。这类似于编写a+b
,而不是自己迭代a
和b
的位,并使用and和XOR来实现半加法器。我理解您的解释并对此表示感谢,但我尝试运行addToSet(sampleSet[0,1,3])
但我收到一个错误,括号用错了。调用只需addToSet sampleSet[0,1,3]
。具体来说,函数调用中不使用括号,除非将子表达式定义为单个参数。函数调用本身就是用空格分隔的函数及其参数。请注意,fooxy
是两个函数调用:foox
返回一个函数,然后将该函数应用于y
。非正式地说,你可以把它看作是对foo
的一次调用,使用两个参数。我有时想知道,我们是否在使用“函数应用程序是并置的”行时对新的Haskeller造成了伤害。也许像其他语言一样,教他们“所有函数都接受一个参数”和“使用parens进行应用”会更好。所以foo(x)(y)(z)
因为我们将foo
应用于x
,然后将foo(x)
应用于y
,然后将foo(x)(y)
应用于z
。然后在以后的某个日期,我们可以告诉他们,作为一种标记方便,您可以在单个令牌或其他东西周围放置paren。。。但我肯定会有一些新的c