如何在 haskell 中编写定点函数
How to write a fixed point function in haskell
我有一个具有以下签名的函数:
simCon :: [Constraint] -> Maybe [Constraint]
我想写一个方法,在 simCon returns Just [Constraint]
的情况下,我想将它们反馈到 simCon 并重新运行该方法,并一直这样做直到输入与输出相同。
如果没有,我想终止算法。
如果输入和输出类型相同,我有一些东西可以工作
fixed :: Eq a => (a -> a) -> a -> a
fixed f a
| a == a' = a
| otherwise = fixed f a'
where a' = f a
但这行不通,因为我 return 现在可能。有人可以建议一种编写类似函数的方法,但要使用 return 类型的 Maybe 吗?
我们可以在这里使用绑定功能:
import Data.Bool(bool)
import Control.Monad(liftM2)
fixedM :: (Eq a, Monad m) => (a -> m a) -> a -> m a
fixedM f = go
where go x = f x >>= (liftM2 bool go pure <*> (x ==))
更详细的实现是:
fixedM :: (Eq a, Monad m) => (a -> m a) -> a -> m a
fixedM f x = do
x' <- f x
if x == x'
then pure x'
else fixedM f x'
因此我们首先计算x'
和f x
。万一f x
returnJust x'
,那我们继续。如果 f x
return Nothing
,fixedM
也会 return Nothing
。然后我们将 x
与 x'
进行比较。如果两者相等,我们 return pure x'
,否则我们递归 fixedM f x'
.
或者,我们可以使用模式匹配,尽管这基本上是使绑定运算符显式化(并且仅适用于Maybe
):
import Control.Monad(ap)
fixedM :: Eq a => (a -> Maybe a) -> a -> Maybe a
fixedM f = ap go f
where go x (Just x') | x == x' = go x' (f x')
| otherwise = Just x'
go _ _ = Nothing
我们可以使用模式保护:
使它更紧凑
fixedM :: Eq a => (a -> Maybe a) -> a -> Maybe a
fixedM f = go
where go x | Just x' <- f x = bool (go x) (Just x) (x == x')
| otherwise = Nothing
我有一个具有以下签名的函数:
simCon :: [Constraint] -> Maybe [Constraint]
我想写一个方法,在 simCon returns Just [Constraint]
的情况下,我想将它们反馈到 simCon 并重新运行该方法,并一直这样做直到输入与输出相同。
如果没有,我想终止算法。
如果输入和输出类型相同,我有一些东西可以工作
fixed :: Eq a => (a -> a) -> a -> a
fixed f a
| a == a' = a
| otherwise = fixed f a'
where a' = f a
但这行不通,因为我 return 现在可能。有人可以建议一种编写类似函数的方法,但要使用 return 类型的 Maybe 吗?
我们可以在这里使用绑定功能:
import Data.Bool(bool)
import Control.Monad(liftM2)
fixedM :: (Eq a, Monad m) => (a -> m a) -> a -> m a
fixedM f = go
where go x = f x >>= (liftM2 bool go pure <*> (x ==))
更详细的实现是:
fixedM :: (Eq a, Monad m) => (a -> m a) -> a -> m a
fixedM f x = do
x' <- f x
if x == x'
then pure x'
else fixedM f x'
因此我们首先计算x'
和f x
。万一f x
returnJust x'
,那我们继续。如果 f x
return Nothing
,fixedM
也会 return Nothing
。然后我们将 x
与 x'
进行比较。如果两者相等,我们 return pure x'
,否则我们递归 fixedM f x'
.
或者,我们可以使用模式匹配,尽管这基本上是使绑定运算符显式化(并且仅适用于Maybe
):
import Control.Monad(ap)
fixedM :: Eq a => (a -> Maybe a) -> a -> Maybe a
fixedM f = ap go f
where go x (Just x') | x == x' = go x' (f x')
| otherwise = Just x'
go _ _ = Nothing
我们可以使用模式保护:
使它更紧凑fixedM :: Eq a => (a -> Maybe a) -> a -> Maybe a
fixedM f = go
where go x | Just x' <- f x = bool (go x) (Just x) (x == x')
| otherwise = Nothing