我一直在使用一些f#解析器和一些流软件,我发现自己越来越多地使用这种模式。我发现它是序列的自然替代,它有一些自然的优势。下面是使用该类型的一些示例函数。
type foldedSequence<'a> =
| Empty
| Value of ' a * (unit -> 'a foldedSequence)
let rec createFoldedSequence fn state =
match fn state with
| None -> Empty
| Some(value, nextState) ->
Value(value, (fun () -> unfold fn nextState))
let rec filter predicate =
function
| Empty -> Empty
| Value(value, nextValue) ->
let next() = filter predicate(nextValue())
if predicate value then Value(value, next)
else next()
let toSeq<'t> =
Seq.unfold<'t foldedSequence, 't>(function
| Empty -> None
| Value(value, nextValue) -> Some(value, nextValue()))这对我很有帮助,我想知道它是否有名字,所以我可以研究一下它的一些技巧和技巧。
发布于 2017-06-11 23:21:39
为了补充现有的答案,我认为Haskellers可能会将这个通用版本称为单列变压器。其想法是您的类型定义看起来几乎像普通的F# list,只是它还有一些附加的方面。你可以想象这样写成:
type ListTransformer<'T> =
| Empty
| Value of 'T * M<ListTransformer<'T>>通过提供特定的M,您可以定义许多事情:
M<'T> = 'T给出了普通的F#列表类型M<'T> = unit -> 'T为您提供了可以懒散地评估的序列。M<'T> = Lazy<'T>为您提供LazyList (缓存已经计算过的元素)M<'T> = Async<'T>给你异步序列同样值得注意的是,在这个定义中,LazyTransformer<'T>本身并不是一个延迟/延迟/异步的值。在某些情况下,这可能会导致问题--例如,当您需要执行一些异步操作以确定流是否为空时--因此更好的定义是:
type ListTransformer<'T> = M<ListTransformerInner<'T>>
and ListTransformerInner<'T> =
| Empty
| Value of 'T * ListTransformer<'T>发布于 2017-06-11 13:01:37
这听起来就像以前在"powerpack“中的LazyList,我认为现在就住在这里:
http://fsprojects.github.io/FSharpx.Collections/reference/fsharpx-collections-lazylist-1.html
https://github.com/fsprojects/FSharpx.Collections/blob/master/src/FSharpx.Collections/LazyList.fs
发布于 2017-06-11 17:40:05
您的类型与迭代器的定义非常接近,既然您已经提到了流,这可能就是您要寻找的概念。
Iteratee是奥列格·基斯列夫概述的一种解决懒惰IO的方法。除了Haskell之外,主要的函数语言都有实现,包括F# (作为FSharpx.Extras的一部分)。
这就是FSharpx如何定义Iteratee的方式
type Iteratee<'Chunk,'T> =
| Done of 'T * Stream<'Chunk>
| Error of exn
| Continue of (Stream<'Chunk> -> Iteratee<'Chunk,'T>)也请看这篇博文:F#中的Iteratee .第1部分。请注意,似乎没有第二部分。
https://stackoverflow.com/questions/44482578
复制相似问题