【问题标题】:How to write a fixed point function in haskell如何在haskell中编写定点函数
【发布时间】:2019-06-20 21:03:58
【问题描述】:

我有一个具有以下签名的函数:

simCon :: [Constraint] -> Maybe [Constraint]

我想编写一个方法,如果 simCon 返回 Just [Constraint],我想将它们反馈回 simCon 并重新运行该方法,并一直这样做直到输入与输出相同。

如果什么都没有,我想终止算法。

如果输入和输出都是相同的类型,我有一些可以工作的东西

fixed :: Eq a => (a -> a) -> a -> a
fixed f a 
  | a == a' = a
  | otherwise = fixed f a'
  where a' = f a

但这行不通,因为我现在返回一个 Maybe。有人可以建议一种编写类似函数但返回类型为 Maybe 的方法吗?

【问题讨论】:

  • 你可以用模式匹配解开它。
  • fixed (>>= simCon)?
  • 你把论点放在哪里了?
  • @Lana 紧随其后,与任何功能一样。

标签: haskell functional-programming fixed-point-iteration


【解决方案1】:

我们可以在这里使用绑定函数:

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'

因此,我们首先用f x 计算x'。如果f x 返回Just x',那么我们继续。如果f x 返回NothingfixedM 也将返回Nothing。然后我们将xx' 进行比较。如果两者相等,我们返回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

【讨论】:

  • 很好地使用了 monad,但我没有看到任何模式匹配?
  • 由于某种原因,第一个函数似乎无限循环
  • @Lana:是的,我交换了gopure
  • @Bergi:是的,我在写答案时改变了主意:)。
  • 非常感谢!
猜你喜欢
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 2010-12-03
  • 2018-03-02
相关资源
最近更新 更多