Haskell - 通过列表列表递归?

时间:2016-02-25 23:31:46

标签: haskell recursion

我似乎无法理解如何在Haskell中的列表列表上进行递归。这是我的问题:

type Symbol = String
type Sentence = [[Symbol]]

getSymbols :: [Sentence] -> [Symbol]
getSymbols [[]] = []
getSymbols ((sym:stmt):(stmts))
    | stmt == [] = getSymbols stmts
    | sym `elem` stmt = getSymbols ((stmt):(stmts))
    | otherwise = sym : getSymbols ((stmt):(stmts))

我正在尝试返回给定句子中找到的所有符号的列表,不存在重复项,例如。

getSymbols [["A","B","C"],["D","A"],["E","B","C"]]

将返回:

["A","B","C","D","E"] --order does not matter--

我一直在尝试一些不同的方法,但似乎无法得到它 - 我仍然在Haskell相当原始,所以也许有一些明显我缺少的东西。非常感谢帮助,谢谢。

3 个答案:

答案 0 :(得分:1)

试试这个:

import Data.List
nub . concat $ [["A","B","C"],["D","A"],["E","B","C"]]

答案 1 :(得分:1)

试试这个:

getSymbols          []  = []
getSymbols (   [] :xss) = getSymbols xss
getSymbols ((x:xs):xss)
    | x `elem` (getSymbols (xs:xss)) =      getSymbols (xs:xss)
    | otherwise                      = x : (getSymbols (xs:xss))

答案 2 :(得分:0)

  

@gallais这需要我写更多功能还是可以   在单一功能完成?因为我想解决问题   只有一个功能

想要简单的解决方案是明智的,但减少使用的函数数量并不是你用Haskell实现这个目标的方式。相反,要找到想要重用定义的简单解决方案。您希望将问题的解决方案看作是针对较小问题的已知解决方案的组合。这可以让你通过记住一点来解决很多问题。

所以,我们从这样的列表开始:

[["A","B","C"],["D","A"],["E","B","C"]]

我们希望找到一个包含所有相同字符串但没有其他字符串且没有重复字符串的列表。如果我们使用concat :: [[a]] -> [a]展平列表怎么办?

["A","B","C","D","A","E","B","C"]

鉴于同样的问题陈述,很明显我们会得出相同的答案。所有重要的是字符串存在;结构的其余部分是无关紧要的。

从这一点开始,我们只需要删除列表中的重复项。有几种方法可以做到这一点。低效率的是nub :: Eq a => [a] -> [a]。更有效的方法是Set.toList . Set.fromList :: Ord a => [a] -> [a] import qualified Data.Set as Set。无论我们选择什么,我们的解决方案如下:

nub . concat

奖励:设计一种方法来删除sort :: Ord a => [a] -> [a]中使用Data.List的重复项。