break (== ' ') :: String -> (String, String)
会产生输入字符串最左侧没有空格的最长前缀和剩余后缀。显然,我们希望以某种方式迭代此过程,将字符串拆分为单词。
State (break (== ' ')) :: State String String
将该函数视为具有状态的计算。请记住State :: (s -> (a, s)) -> State s a
,因此输出状态是右侧组件。所以初始状态是输入字符串,而break (== ' ')
被视为一个State
操作,通过return
返回第一个单词并更新状态到剩余后缀。
现在将其与modify (drop 1)
组合以删除下一个空格,并重复此过程。请注意,它在开头附加到输入(' ' :)
,并以modify
开始。
(sequence . repeat) (modify (drop 1) >> State (break (== ' ')))
:: State String [String]
= do
modify (drop 1)
s1 <- State (break (== ' '))
modify (drop 1)
s2 <- State (break (== ' '))
modify (drop 1)
s3 <- State (break (== ' '))
...
repeat
构造一个无限列表,其中包含同一两步动作
modify (drop 1) >> State (break (== ' '))
。
sequence
接受一系列操作并运行它们,在列表中收集结果。这里我有些含糊不清,但由于这是“惰性状态单子”(存在着严格的状态单子而这不是),所以事情会变得容易,使得
sequence
可以运行一个无限的操作列表,并在需要时生成相应的无限结果列表。
如上所示,您将获得一个无限计算,生成所有
State (break (== ' '))
步骤的无限结果列表。
["hello", "world", "", "", ...]
takeWhile (not . null)
很明显就是自描述的: 它会取出列表中非空元素,直到遇到空元素。
["hello", "world"]