简化Haskell函数

时间:2014-11-09 08:41:29

标签: haskell

我正在编写小函数来切断给定长度的数据包中的字符串,但我是Haskell的初学者,我想我可以简化我的功能。他们在这里:

packetAux _ [] = []
packetAux 0 ls = [] 
packetAux n l@(x:xs) = if n > (length l) then [] else x : packetAux (n - 1) xs

packet _ [] = []
packet 0 l = []
packet n l@(x:xs) = [x | x <- ((packetAux n l) : (packet n xs)), x /= ""]

Ex:包2“12345”给出[“12”,“23”,“34”,“45”]

我怎么能避免 1)packetAux和packet中的重复 2)用x / =“”过滤包中的结果?

2 个答案:

答案 0 :(得分:5)

您的功能是

import Data.List (tails)

packets :: Int -> [a] -> [[a]]
packets n xs = filter ((==n).length) $ map (take n) $ tails xs

另一种写作方式是

packets n xs = foldr (zipWith (:)) (repeat []) $ take n $ tails xs

这两种变体实际上也会以无用的方式在无限列表上工作。

$运算符只是为了便于分组而没有括号:

f $ g $ x = f ( g ( x ) ) 

答案 1 :(得分:2)

一般的诀窍是使用Hoogle或Hayoo!检查是否存在类似的功能。 数据包的签名是:

Int -> [Char] -> [[Char]]

如果您使用以上内容填写Hoogle,在第一批结果中您将获得具有非常相似签名的函数:

Int -> [a] -> [a]

它采用给定列表的“n”个第一个元素。

这将有助于我们减少功能的主要部分:

packet n (x:xs) = [[x] ++ take (n-1) xs] ++ packet n xs

现在,由于你不希望函数在列表长度小于n值时返回一个值,我们可以使用guards来保持简单:

packet n l@(x:xs)
    | length l < n = []
    | otherwise    = [[x] ++ take (n-1) xs] ++ packet n xs

请注意,有可能通过减少对length函数的调用次数来提高速度。我们可以保留索引,而不是每次都调用它。但是,它显然意味着更多的代码......

相关问题