一个haskell函数来测试一个整数是否出现在另一个整数之后

use*_*850 4 algorithm haskell

我正在编写一个名为after的函数,它将整数列表和两个整数作为参数.在列表之后num1 num2应该返回True如果列表中出现num1并且列表afternum1中出现num2.(不一定紧接在之后).

after::[Int]->Int->Int->Bool
after [] _ _=False
after [x:xs] b c 
    |x==b && c `elem` xs =True 
    |x/=b && b `elem` xs && b `elem` xs=True
Run Code Online (Sandbox Code Playgroud)

这就是我到目前为止,我最大的问题是我不知道如何强制num2在num1之后.

Chr*_*ner 7

有几种不同的方法来处理这个问题; 虽然很容易直接进行递归,但如果有另一个选项,最好避免显式使用递归.

这是一个使用一些列表实用程序的简单版本.请注意,我们操作的对象通常是最后一个参数,这是一个Haskell习语.在这种情况下,切换参数允许我们将其写为管道,其中第三个参数(列表)隐式传递:

after :: Int -> Int -> [Int] -> Bool
after a b = elem b . dropWhile (/= a)
Run Code Online (Sandbox Code Playgroud)

希望这很容易理解; 我们删除列表中的元素直到我们命中a,假设我们找到一个,我们检查b剩下的列表中是否有a .如果没有a,那么这个列表[]显然没有b,所以它按预期返回False.

你没有说明如果'a'和'b'相等会发生什么,所以我会让你自己调整它以适应那种情况.提示:添加一个tail地方;)

如果您有兴趣,可以采用以下几种方法:

使用折叠很容易处理;

我们有三种状态可以建模.要么我们正在寻找第一个元素,要么我们正在寻找第二个元素,或者我们已经找到它们(按照正确的顺序).

data State =
  FindA | FindB | Found
  deriving Eq
Run Code Online (Sandbox Code Playgroud)

然后我们可以将列表"折叠"(也就是减少)到它是否匹配的结果.

after :: Int -> Int -> [Int] -> Bool
after a b xs = foldl go FindA xs == Found
  where
    go FindA x = if x == a then FindB else FindA
    go FindB x = if x == b then Found else FindB
    go Found _ = Found
Run Code Online (Sandbox Code Playgroud)

如果您愿意,也可以递归地执行:

after :: Int -> Int -> [Int] -> Bool
after _ _ [] = False
after a b (x:xs) 
  | x == a = b `elem` xs
  | otherwise = after a b xs
Run Code Online (Sandbox Code Playgroud)

干杯!