[] 的 MonadFix 实例
MonadFix instance for []
实例定义为
instance MonadFix [] where
mfix f = case fix (f . head) of
[] -> []
(x:_) -> x : mfix (tail . f)
但是我没能理解它背后关于被视为非确定性计算的 []
monad 的直观含义。在 mfix f
中,函数 f
的参数必须不严格,因此无法检查参数。根据定义,它也不能在其输出的任何地方使用参数,否则在某些时候它会达到 fix (f . head)
并发散。那么除了 mfix (const someList)
之外,mfix
对列表有什么用处(或很好的例子)吗?
如果您将所有 fix
变体与严格函数一起使用,它们都会有问题,但这 在实际用例中通常不是问题†:a
基本上都是函数类型,任何lambda都已经在NF中了。
所以,至于具体用途……嗯,这里至少有收敛的东西:
f :: (Int -> Int) -> [Int -> Int]
f f' = [\x -> if x>0 then f' (x-1) * i else 1 | i<-[0..]]
f
基本上生成一个幂函数列表。
GHCi> take 20 $ mfix f <*> [1,2]
[0,0,1,1,2,4,3,9,4,16,5,25,6,36,7,49,8,64,9,81]
我不确定这到底有什么用,但它确实有非常有趣的行为。
我刚刚注意到这是一个不好的例子,因为它实际上等同于单个 fix (f . head)
。嗯...
†你似乎说得很对:是 a -> [a]
的问题], 因为没有明显的方法可以使列表结构依赖于参数而不严格。
这样说可能最简单。 mfix f
完全定义的函数f
是f x
的脊椎不依赖于x
的函数,所以可以写成[=22] =]
f x = [f1 x, ..., fn x]
对于某些 n
(可能无穷大)和某些 f1
,...,fn
。然后
mfix f = [fix f1, ..., fix fn]
(当然,要真正完全定义,还必须定义每个 fix fi
)。
mfix
可以被认为是非确定性地为您提供非确定性函数的不动点。相当严格的限制是非确定性计算的形状不能以任何方式依赖于输入。我们似乎需要对计算进行某种限制才能开始,但您可能希望至少能够有条件地终止计算的一个分支(比如某些中间计算是否为负数)。我一直认为应该可以通过使用不同的非确定性 monad 以这种方式使用 mfix
,其选择操作不是关联的,但从未制定出细节。
实例定义为
instance MonadFix [] where
mfix f = case fix (f . head) of
[] -> []
(x:_) -> x : mfix (tail . f)
但是我没能理解它背后关于被视为非确定性计算的 []
monad 的直观含义。在 mfix f
中,函数 f
的参数必须不严格,因此无法检查参数。根据定义,它也不能在其输出的任何地方使用参数,否则在某些时候它会达到 fix (f . head)
并发散。那么除了 mfix (const someList)
之外,mfix
对列表有什么用处(或很好的例子)吗?
如果您将所有 fix
变体与严格函数一起使用,它们都会有问题,但这 在实际用例中通常不是问题†:a
基本上都是函数类型,任何lambda都已经在NF中了。
所以,至于具体用途……嗯,这里至少有收敛的东西:
f :: (Int -> Int) -> [Int -> Int]
f f' = [\x -> if x>0 then f' (x-1) * i else 1 | i<-[0..]]
f
基本上生成一个幂函数列表。
GHCi> take 20 $ mfix f <*> [1,2]
[0,0,1,1,2,4,3,9,4,16,5,25,6,36,7,49,8,64,9,81]
我不确定这到底有什么用,但它确实有非常有趣的行为。
我刚刚注意到这是一个不好的例子,因为它实际上等同于单个 fix (f . head)
。嗯...
†你似乎说得很对:是 a -> [a]
的问题], 因为没有明显的方法可以使列表结构依赖于参数而不严格。
这样说可能最简单。 mfix f
完全定义的函数f
是f x
的脊椎不依赖于x
的函数,所以可以写成[=22] =]
f x = [f1 x, ..., fn x]
对于某些 n
(可能无穷大)和某些 f1
,...,fn
。然后
mfix f = [fix f1, ..., fix fn]
(当然,要真正完全定义,还必须定义每个 fix fi
)。
mfix
可以被认为是非确定性地为您提供非确定性函数的不动点。相当严格的限制是非确定性计算的形状不能以任何方式依赖于输入。我们似乎需要对计算进行某种限制才能开始,但您可能希望至少能够有条件地终止计算的一个分支(比如某些中间计算是否为负数)。我一直认为应该可以通过使用不同的非确定性 monad 以这种方式使用 mfix
,其选择操作不是关联的,但从未制定出细节。