这里可能会让人感到困惑的一件事是过度使用list
。我将开始使用Haskell符号来解决您的问题。 ::
表示“具有类型”,[Foo]
表示“Foo列表”。
list1 :: [Symbol]
list2 :: [Number]
type Pair = (Symbol, Number)
(combiner list1 list2) :: [Pair]
现在看起来你想用foldr
来处理list2的问题。
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr需要一个step :: a -> b -> b
和一个start :: b
。由于我们希望最终的结果是一个[Pair]
,这意味着b = [Pair]
。start
可能是空列表。由于list2填充了[a]
槽,这意味着a = Number
。因此对于我们的问题,step :: Number -> [Pair] -> [Pair]
combiner :: [Symbol] -> [Number] -> [Pair]
combiner list1 list2 = foldr step start list2
where step :: Number -> [Pair] -> [Pair]
step a b = undefined
start = []
到目前为止,这与您编写的foldr
相同,只是我还没有定义step
。那么,什么是步骤函数?从类型上来看,我们知道它必须接受一个Number
和一个[Pair]
并生成一个[Pair]
。但是这些输入意味着什么?嗯,Number
输入将是list2
的某个元素。而[Pair]
输入将是“到目前为止折叠的结果”。因此,我们将想要取得我们的Number
,并做一些事情以创建Pair
,然后将它们贴到迄今为止的结果上。这是我的代码开始与您的代码不同的地方。
step a b = append (doSomething a) b
doSomething :: Number -> [Pair]
doSomething a = undefined
由于您使用Racket,可能会将doSomething
定义为匿名函数,这意味着list1
在作用域内。(因为它在Haskell函数的where子句中,所以它在作用域内)。您可能会使用该列表生成组合。
doSomething a = ... a ... list1 ...
实现doSomething
留给读者作为练习,将其翻译回Racket也是如此。请注意,我在这里定义的Haskell函数combiner
的类型签名可以泛化为[a] -> [b] -> [(a,b)]
。