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