结合多个Haskell函数

时间:2018-02-11 19:14:17

标签: function haskell functional-programming

我想知道是否有一种简单的方法可以将这些功能组合在一起,使其更加干净。该函数的目的是获取一个int列表,并返回一个列表,其中包含在给定的int出现后发生的所有元素。

listAfterFinalKey:: [Int] -> Int -> [Int]

我的代码有效,我只是想知道是否有更好的编写方法。理想情况下,我希望将它全部放在一个函数中(listAfterFinalKey),但我不知道如何让它工作,而不是有三个独立的函数。我也避免在库中进行任何构建,以及诸如let和where之类的东西。如果有人能告诉我如何组合或压缩一些代码(如果可能的话),我将不胜感激。

listAfterFinalKey:: [Int] -> Int -> [Int]
listAfterFinalKey [] x = []
listAfterFinalKey x y = helperFunction1 x y (checker x y 0)

checker:: [Int] -> Int -> Int -> Int
checker [] tracker count = count
checker (x:xs) tracker count = if tracker == x
    then checker xs tracker (count+1)
    else checker xs tracker count


helperFunction1:: [Int] -> Int -> Int -> [Int]
helperFunction1 [] tracker count = []
helperFunction1 x tracker count = if (count == 0)
    then take 1 x ++ helperFunction1 (drop 1 x) tracker count
    else if (count /= 0) && (tracker == (head x))
    then helperFunction1 (drop 1 x) tracker (count-1)
    else helperFunction1 (drop 1 x) tracker count

1 个答案:

答案 0 :(得分:1)

如果你真的想要对函数式编程有一个良好的感觉,可以不立即使用各种内置函数。然而,其中许多函数都是函数式编程的体现,所以学习使用它们很有用,也许还可以学习如何复制它们。

内置的Haskell模块(事实上,我遇到的所有Haskell模块)都是开源的,因此您可以轻松查看它们的实现方式。

为了重现上述行为,您可以实施自己的elemdropWhiletail版本:

elem' :: Eq a => a -> [a] -> Bool
elem'      _    [] = False
elem' target (x:xs) | target == x = True
elem' target (_:xs) = elem' target xs

dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' _ [] = []
dropWhile' p (x:xs) | p x = dropWhile' p xs
dropWhile' _ xs = xs

tail' :: [a] -> [a]
tail' (_:xs) = xs

这三个功能非常类似于他们的“官方”功能 - 我刚刚为这三个功能添加了'作为后缀。

现在,您可以使用这三个构建块轻松实现listAfterFinalKey

listAfterFinalKey :: Eq a => [a] -> a -> [a]
listAfterFinalKey xs target | not (elem' target xs) = xs
listAfterFinalKey xs target = tail' (dropWhile' (/= target) xs)

据我所知,它的行为与OP版本相似:

*Q48735389> listAfterFinalKey [0..9] 3
[4,5,6,7,8,9]
*Q48735389> listAfterFinalKey [0..9] 11
[0,1,2,3,4,5,6,7,8,9]
*Q48735389> listAfterFinalKey [0..9] (-1)
[0,1,2,3,4,5,6,7,8,9]
*Q48735389> listAfterFinalKey [1,2,3,2,1] 2
[3,2,1]

它不仅会在遇到target之前删除所有元素,而且如果target根本不存在,它也会返回原始列表。这是AFAICT,也是OP功能的行为。

通常,head(和head')是不安全的,因为它在传递空列表时会抛出异常。但是,在这个简单的函数中,永远不会发生这种情况,因为tail'仅在我们知道的情况下被调用,target中至少出现xs }。

另请注意,listAfterFinalKey的类型比OP版本更为通用。