我对Haskell相对较新,我正在努力想出一种实现Haskell span
函数的方法。但是,我的问题比我不知道如何使函数返回列表列表或包含我想要的元素的元组列表的问题更为普遍。我的列表列表存在问题,例如:
[[1],[2]]
是我无法使该函数向列表列表中的第一个列表添加元素。我只知道如何将另一个列表附加到列表列表中。
简而言之,如果你向我解释如何实现span
功能,那么这一切都应该为我所知。
答案 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
条件下的模式匹配。这意味着我们:
span pred xs
; prefix'
和suffix'
的第一个和第二个元素。我怀疑步骤#2,即递归调用结果的模式匹配,是你可能不理解的。
第二个不明显的事情是递归。这是一个棘手的事情,因为,反作用,要解决递归问题,你需要假设你已经解决了它,但是对于“错误的”论证 - 如果你还没有解决它,那么你想要采取一个艰难的步骤!但诀窍在于:
prefix'
和suffix'
变量包含的内容:正确的解决方案,但错误的列表 - 您实际尝试解决的问题的尾部。