我最近开始在Haskell中学习函数式编程,但要解决一些问题,它要求使用递归和基本系统函数为列表创建自己的某些系统函数版本。我需要编写的功能是:
!!
(列表中的第n个项目)append
(将列表合并在一起)subst
(替换),例如subst 'x' 'y' ['q','x','r','x','s']
〜>['q','y','r','x','y','s']
intersection
例如intersection [2,5,7] [9,7,3,5]
〜>[5,7]
union
联合例如union [2,5,7] [9,7,3,5]
〜>[2,5,7,9,3]
reverse
例如reverse [4,5,6,7]
〜>[7,6,5,4]
我从第一个开始,并写了一个这样的定义:
nthelement :: Eq a => [a] -> a -> a
用命令式语言我会做一个计数器变量(例如i
)并使用系统函数tail
删除list的第一个元素直到i = n
。但是,当我了解到在函数中只能执行常量操作时,我想不出一种方法来决定何时停止重复执行并返回元素,而不是重新tail
调用函数直到列表为空。
请帮我解决这个问题。对执行第一个功能或其中任何一个的任何帮助都将非常好。谢谢。
在这里,我仅对您提出的问题之一提供一般性答案。我希望这可以帮助您更好地理解一般问题,并针对您的特定问题/任务提出解决方案。
用命令式语言,我将创建一个计数器变量(例如i),然后使用系统功能tail删除列表的第一个元素,直到i = n。但是,正如我了解到的那样,在函数中只能执行常量操作,我想不出一种方法来决定何时停止重复执行并返回元素,而不是重新调用tail函数直到列表为空。
您始终可以使用状态变量“模拟” for循环,并使用递归打破循环:
Python:
def foo(xs):
state = initial_state
for x in xs:
state = make_new_state(x, state)
if not condition(state, x):
break
return state
在等效的Haskell代码中,您将使用内部函数以及该状态的额外参数。您还可以在上公开额外的参数,foo
但通常您不想将其公开给的调用者foo
:
foo xs = go initialState xs
where go [] state = state
go (x:xs) state = if not (condition state x)
then state
else go xs (makeNewState x state)
对于许多算法,根本不需要中断循环,在这种情况下,“模式”变为:
foo xs = go initialState xs
where go [] state = state
go (x:xs) state = go xs (makeNewState x state)
makeNewState
您在每个步骤执行的逻辑在哪里(当然,不必在单独的函数中执行)。
对于后一种情况,有一些通用函数foldr
和foldl
和foldl'
,例如:
foo xs = foldr makeNewState initialState xs
此外:还有诸如State monad之类的东西,它可以让您以纯粹的方式编写命令式逻辑,但是最好先理解诸如“原始”递归和折叠之类的东西,然后才继续学习诸如monads和显式状态之类的东西。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句