Dan*_*Dos 8 monads haskell fixpoint-combinators
考虑以下数据类型:
data Foo = Halt | Iter Foo
Run Code Online (Sandbox Code Playgroud)
这是 的不动点Maybe
。它包含序列、、等的直接极限,其中是注入态射。然而,有一个元素没有被直接极限覆盖,即。Void
Maybe Void
Maybe (Maybe Void)
pure
Foo
fix Iter
让我再举一个例子:
data Bar = Bar Bar Bar
Run Code Online (Sandbox Code Playgroud)
这是 的不动点Complex
。由于Void
、Complex Void
、Complex (Complex Void)
等都同胚于Void
,所以直接极限也Void
。然而,Bar
有一个元素,即fix (join Bar)
。
那么这些“剩余”元素的数学依据是什么?
正如评论中所指出的,这些元素的存在是由于不终止的结果。
\n在终止语言中,或者等效地,在集合范畴中, 的初始代数(最小不动点)是Maybe
,( )Nat
的初始代数是空类型。并且不存在,因为无法在终止语言中定义。Complex
data Complex a = Complex a a
Void
fix Iter
fix (join Complex)
fix
由于无限制的非终止,集合不再是一个好的类型模型,因为无限循环存在于所有类型中。在这种情况下,常见的替代方案是DCPO或一些类似的订单结构。特别是,递增序列的底部和极限的存在正是需要能够定义的fix
(通过克莱恩定理)。例如,在 的情况下data Nat = Z | S Nat
,获得作为序列, , ,等fix S
的极限。\xe2\x8a\xa5
S \xe2\x8a\xa5
S (S \xe2\x8a\xa5)
S (S (S \xe2\x8a\xa5))
您确实需要小心底部的位置。例如,在 Haskell 中,是由、和Maybe a
组成的 DCPO ,代表的居民。您还可以定义严格变体:\xe2\x8a\xa5
Nothing
Just x
x
a
data SMaybe a\n = Nothing\n | Just !a\n
Run Code Online (Sandbox Code Playgroud)\n作为 DCPO 包含\xe2\x8a\xa5
, Nothing
,并且Just x
对于的非底层x
居民。特别是,序列、、等不再明确定义(或者如果你真的想给它一个值,它将始终等于),因此你不再有办法构造 、 的无限序列,实际上, 的初始代数(最小不动点)仅包含应用于/的/的有限序列,并且是单独的。a
\xe2\x8a\xa5
Just \xe2\x8a\xa5
Just (Just \xe2\x8a\xa5)
\xe2\x8a\xa5
Just
SMaybe
Just
S
Nothing
Z
\xe2\x8a\xa5
请注意,这并不限于惰性语言。DCPO 也可以用来建模严格的语言。只是值和计算之间存在明确的区别,这在某种程度上使事情变得更加明显。例如ML中的选项类型
\ntype \'a option = None | Some of \'a\n
Run Code Online (Sandbox Code Playgroud)\nNone
对应于由和Some x
for x
in组成的值集\'a
。但类型unit -> \'a option
并不是从unit
值到\'a option
值的纯函数。unit
它是一个从to 计算结果的函数\'a option
。结果类型的计算表示提升类型t
的元素(即,底部或 中的值)。因此,您可以将 Haskell 用作一种类型的 thunk,并以严格的语言对 Haskell 中发生的所有事情进行编码。 {\xe2\x8a\xa5} + t
t
unit -> _
归档时间: |
|
查看次数: |
197 次 |
最近记录: |