在Haskell中创建inits函数

时间:2014-11-29 01:59:03

标签: haskell

好吧所以这是一个有趣的情况(imo)

这是我的代码:

tails' :: [a] -> [[a]]
tails' [] = []
tails' (x:xs) = tail (x:xs) : tails' xs

inits' :: [a] -> [[a]]
inits' [] = []
inits' (x:xs) = init(x:xs) : inits' xs

eightB :: (Eq a) => [a] -> [a] -> Bool

eightB xs ys = elem xs (tails' ys ++ inits' ys)

我正试图通过向你学习哈斯克尔的大好事来解决“大海捞针”问题;以我自己的方式。

我遇到的问题是,当我尝试输入时:

inits' [1,2,3,4,5]

进入ghci,我得到:

[[1,2,3,4],[2,3,4],[3,4],[4],[]]

该函数在第一次迭代时工作正常,但由于某种原因决定在第一次迭代后切换到尾函数(至少这是我认为发生的事情)。

感谢您的帮助!

编辑:修正了一个拼写错误

4 个答案:

答案 0 :(得分:2)

@Iuqui帮助我得到了这个答案。

inits' :: [a] -> [[a]]
inits' [] = []
inits' xs = init xs : inits' (init xs)

答案 1 :(得分:1)

我知道这已经有好几年了,但我想我会提到 inits' 对于生成 search/isInfixOf 函数的实现并不是很有用。上面的代码检查针是否等于尾部之一或初始值之一,而不是它是否包含在某处。现在,如果您出于某种原因确实想计算您的 eightB 函数,那么您可以更便宜地进行计算:

eightB xs ys =
  (xs `isPrefixOf'` ys)
  || (reverse xs `isPrefixOf'` reverse ys)

xs `isPrefixOf'` ys = and (zipWith (==) xs ys)

答案 2 :(得分:0)

问题是,tail中的模式匹配中存在一种固有的inits'函数。

inits' (x:xs) = ....

这将列表分为两部分

x = head theList
xs = tail theList

当你递归时,你只使用尾部

inits' (x:xs) = <stuff ....> : inits' xs

您真正想要做的是将列表的init传递给递归。不幸的是,您无法使用模式匹配将列表分解为initlast。您可以在where中轻松完成此操作。

这可能就是你想做的事情

inits' :: [a] -> [[a]]
inits' [] = []
inits' theList = i:inits' i
  where
    i = init theList

答案 3 :(得分:-1)

init 中使用 inits 存在一个巨大的问题,即 init 无法返回任何有意义的或对无限列表正确的内容。

inits 有替代方案

最简单的是

[ [1..i] | i <- [1..] ]

它将永远输出。与它一起使用 take 是明智的。

函数应该接近全函数。

ins ls = [ take i ls | i <- [1..] ]

take 6 $ ins ['a'..]
["a","ab","abc","abcd","abcde","abcdef"]

这些是无限的 tails 函数。第一个,只有数字。第二个,任何。

> tlsn  =  [ replicate i i | i <- [1..] ]
> tls xs = [ replicate i x |(i,x) <- zip [1..] xs ]
> take 5 tlsn
[[1],[2,2],[3,3,3],[4,4,4,4],[5,5,5,5,5]]

这是tailstails的换位,都是从上到下

1 2 3 4 5    1
  2 3 4 5    2 2
    3 4 5    3 3 3
      4 5    4 4 4 4
        5    5 5 5 5 5 

> transpose.take 5 $ tlsn
[[1,2,3,4,5],[2,3,4,5],[3,4,5],[4,5],[5]]

transpose 不会转置无限列表。

怎么办?