这是Funator还是Monad?

时间:2014-05-27 17:52:48

标签: haskell

我在C#中实现了自己的Promise结构,想在Haskell中测试这个概念,所以经过一些严重的脑力训练(对此仍然很新),我制作了

data Promise f a =  PendingPromise f | ResolvedPromise a | BrokenPromise deriving( Show )

class Future p where
        later :: (b -> c) -> p (a -> b) b -> p (a -> c) c
        resolve :: p (a -> b) a -> a -> p (a -> b) b

instance Future Promise where
        later g (PendingPromise f) = PendingPromise (g . f)
        later g (ResolvedPromise a) = ResolvedPromise (g a)
        resolve (PendingPromise f) a = ResolvedPromise (f a)

弄清楚如何编写此数据类型Promise f a真是令人头疼。

无论如何,later方法似乎是某种Applicative Functor而Promise应该是Monads。我是否可以让Promise成为某个的实例并获得此功能而不是实现我自己的类Future?


修改 感谢@bheklilr,later函数被证明是fmap的伪装,稍微重新定义了数据类型

data Promise a b =  PendingPromise (a -> b) | ResolvedPromise b | BrokenPromise

instance Functor (Promise c) where
    fmap f (PendingPromise g) = PendingPromise (f . g)
    fmap f (ResolvedPromise a) = ResolvedPromise (f a)
    fmap f BrokenPromise = BrokenPromise

知道(Promise a)是一个Functor,更容易看出为什么是Monad。

3 个答案:

答案 0 :(得分:9)

是的,这是一个单子。最简单的方法是观察Promise f a ≅ Maybe (Either f a),因此它也与变换器等效同构,它具有已经过验证的标准monad实例。

type Promise' f = ErrorT f Maybe

promise2Trafo :: Promise f a -> Promise' f a
promise2Trafo (PendingPromise f) = ErrorT . Just $ Left f
promise2Trafo (ResolvedPromise a) = ErrorT . Just $ Right a
promise2Trafo BrokenPromise = ErrorT Nothing

trafo2Promise :: Promise' f a -> Promise f a
trafo2Promise = ... -- straightforward inverse of `promise2Trafo`

instance Applicative Promise where
  pure = trafo2Promise . pure
  fp <*> xp = trafo2Promise $ promise2Trafo fp <*> promise2Trafo xp

等等。

答案 1 :(得分:6)

您要做的是尝试为Functor实施实例,并检查它是否符合Functor Laws。从实例开始:

instance Functor (Promise f) where
    fmap f (PendingPromise g) = PendingPromise g
    fmap f (ResolvedPromise a) = ResolvedPromise (f a)
    fmap f BrokenPromise = BrokenPromise

这是否符合Functor Laws?由于PendingPromiseBrokenPromise的案例始终是身份,因此我会将其排除在外:

-- fmap id = id
fmap id (ResolvedPromise a) = ResolvedPromise (id a) = ResolvedPromise a

-- fmap (f . g) = fmap f . fmap g
fmap (f . g) (ResolvedPromise a) = ResolvedPromise (f (g a))
fmap f (fmap g (ResolvedPromise a)) = fmap f (ResolvedPromise (g a)) = ResolvedPromise (f (g a))

所以是的,它确实符合Functor法则。

接下来,看看您是否可以编写ApplicativeMonad个实例并证明它们符合相应的法律。如果您可以编写一个实例,那么您的数据类型为Monad,与Future类无关。

答案 2 :(得分:0)

这是我提出的最终代码,如果对某人有用的话。 Promise是Functor类的一个实例,这是一个问题,但也实现了Future类来解决这个承诺,可能会得到它的价值,并做出新的承诺。

data Promise a b =  Pending (a -> b) | Resolved b | Broken

class Future p where
        resolve :: p a b -> a -> p a b
        getValue :: p a b -> Maybe b
        makePromise :: p a a

instance Future Promise where
        resolve (Pending f) a = Resolved (f a)
        resolve (Resolved a) _ = Resolved a
        resolve Broken _ = Broken

        getValue (Resolved a) = Just a
        getValue (Pending _) = Nothing
        getValue Broken = Nothing

        makePromise = Pending id

instance Functor (Promise a) where
        fmap f (Pending g) = Pending (f . g)
        fmap f (Resolved a) = Resolved (f a)
        fmap f Broken = Broken