Haskell的跨度函数

时间:2015-02-09 09:53:49

标签: haskell recursion

我对Haskell相对较新,我正在努力想出一种实现Haskell span函数的方法。但是,我的问题比我不知道如何使函数返回列表列表或包含我想要的元素的元组列表的问题更为普遍。我的列表列表存在问题,例如:

[[1],[2]]

是我无法使该函数向列表列表中的第一个列表添加元素。我只知道如何将另一个列表附加到列表列表中。

简而言之,如果你向我解释如何实现span功能,那么这一切都应该为我所知。

2 个答案:

答案 0 :(得分:1)

所以我认为你所说的是你知道如何通过做类似

之类的方式递归追加到列表中
foobar :: [x] -> [y]
foobar (  []) = []
foobar (x:xs) = {- ...stuff... -} : foobar xs

但您不知道如何使用两个列表执行此操作:

foobar :: [x] -> ([y], [z])
foobar (x:xs) = ???

一般情况下,如果结果不是列表,而是包含列表的内容,那么最终会执行以下操作:

foobar :: [x] -> ([y], [z])
foobar (x:xs) =
  let
    y = {- whatever -}
    z = {- whatever -}
    (ys, zs) = foobar xs   -- The recursive call
  in  (y:ys, z:zs)

如果结果是monadic动作

,则同样适用
foobar :: [x] -> IO [y]
foobar (x:xs) = do
  y  <- {- whatever -}
  ys <- foobar xs
  return (y:ys)

请注意,这会强制该函数不会延迟。

答案 1 :(得分:0)

我认为你想在这里使用的一般模式如下:

span :: (a -> Bool) -> [a] -> ([a], [a])
span pred [] = ([], [])
span pred (x:xs) = if pred x then _ else _  -- fill in the blanks
    where (prefix', suffix') = span pred xs

那里有两件非显而易见的事情。首先,请注意where条件下的模式匹配。这意味着我们:

  1. 调用生成一对列表的span pred xs;
  2. 此对上的模式匹配;
  3. 分别命名对prefix'suffix'的第一个和第二个元素。
  4. 我怀疑步骤#2,即递归调用结果的模式匹配,是你可能不理解的。

    第二个不明显的事情是递归。这是一个棘手的事情,因为,反作用,要解决递归问题,你需要假设你已经解决了它,但是对于“错误的”论证 - 如果你还没有解决它,那么你想要采取一个艰难的步骤!但诀窍在于:

    • 想象一下,您实际上已经解决了问题,但对于列表的尾部。这就是prefix'suffix'变量包含的内容:正确的解决方案,但错误的列表 - 您实际尝试解决的问题的尾部。
    • 鉴于(非)解决方案,您如何重复使用它来为 问题找到正确的解决方案?