我正在教自己在Haskell中编程,我正在研究一个find函数。它的作用是需要两个字符串,例如"hello"
和"he"
,并计算"he"
中"hello"
出现的次数。
find函数需要跟踪几个事情,例如在列表中找到的单词的次数,不需要在函数的开头输入。因此,我将该功能分解为两个较小的功能:一个用户最初输入数据,然后将数据导向第二个执行工作的功能。
这是我的代码:
search :: (Eq a) => [a] -> [a] -> Integer
search [] _ = 0
search _ [] = 0
search x y = search1 x y y 0
search1 :: (Eq a) => [a] -> [a] -> [a] -> Integer -> Integer
search1 _ _ [] n = n
search1 x [] z n = search1 x z z (n+1)
search1 [] _ _ n = n
search1 (x:xs) (y:ys) z n
| x == y = search1 xs ys z n
| otherwise = search1 xs (y:ys) z n
在其中,我创建函数search1
以“插入”,而不是用函数search
开始,这需要一些冗余供用户输入的函数。用户的数据search1
。
我的问题是,创建一个“插入”冗余数据的功能是Haskell的一个好习惯吗?或者我应该做些不同的事情?
答案 0 :(得分:7)
是的,这是一种很好的做法。但是,通常最好将第二个函数设置为第一个函数,如果它本身没有用,并且仅作为另一个函数的工作者。
如果你在包装器的本地创建一个worker,你可以在worker的主体中引用包装器的参数,而不将它们作为参数传递给worker,这通常有助于提高性能。
对于您的示例,本地工作者的函数可能看起来像
search :: (Eq a) => [a] -> [a] -> Integer
search [] _ = 0
search _ [] = 0
search hay needle = search1 hay needle 0
where
search1 x [] n = search1 x needle (n+1)
search1 [] _ n = n
search1 (x:xs) (y:ys) n
| x == y = search1 xs ys n
| otherwise = search1 xs (y:ys) n
我已经删除了一个在递归调用中从未改变的worker的一个参数。此外,使本地工作人员无需检查空needle
。