2015-02-09 58 views
1

我对Haskell来说比较新,我很想找出实现Haskell的span函数的方法。然而,我的问题比这更一般,因为我不知道如何让一个函数返回包含我想要的元素的列表或包含元组列表的列表。我和列表,如清单问题:Haskell的跨度函数

[[1],[2]] 

的是,我不能让功能列表清单中的元素添加到第一个列表。我只知道如何将另一个列表附加到列表中。

总之,如果你向我解释如何实现span函数,这一切应该有希望清楚地告诉我。

+1

你看过实际的实现吗? http://haddocks.fpcomplete.com/fp/7.8/20140916-162/base/src/GHC-List.html#span – 2015-02-09 10:28:34

+1

嗯。如何编写'addToFirstInList :: a - > [[a]] - > [[a]]'是不是真正的问题?毕竟,你谈论的是“列表清单”,而“span”则返回列表的列表。 – Zeta 2015-02-09 10:32:37

+2

如果你的问题是关于添加一个元素到列表的第一个列表,然后说实话,我认为你应该阅读列表(推荐真实世界Haskell /学习你一个Haskell)。如果它真的关于'span',那么你应该编辑它以更好地表明你的意图 – joozek 2015-02-09 10:33:35

回答

1

所以我觉得什么你的意思是,你知道如何递归做类似

foobar :: [x] -> [y] 
foobar ( []) = [] 
foobar (x:xs) = {- ...stuff... -} : foobar xs 

追加到一个列表,但你不知道怎么做,与2名名单:

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) 

同样适用如果说,结果是一元行动

foobar :: [x] -> IO [y] 
foobar (x:xs) = do 
    y <- {- whatever -} 
    ys <- foobar xs 
    return (y:ys) 

注意,这迫使该功能不能偷懒。

+0

哦,我明白了!我想我现在明白了!我通常不会在StackOverflow上提出这样简单的问题,但我在网上找不到任何帮助......我认为随着我进一步阅读“真实世界Haskell”这本书,它也会变得更加清晰。谢谢! – Prince 2015-02-09 17:37:28

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'中的第一个和第二个元素。

我怀疑,第2步,递归调用的结果模式匹配,你可能不知道。

第二个非显而易见的事情是递归。这是一件棘手的事情,因为,为了解决递归问题,你需要假设你已经解决了这个问题,但是对于“错误的”论点 - 如果你还没有解决它,想象一下你自己采取的一个艰难的步骤!但关键是这样的:

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