这是Funator还是Monad?

Cri*_*cia 6 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)
Run Code Online (Sandbox Code Playgroud)

弄清楚如何编写这种数据类型Promise f a真的很头疼.

无论如何,该later方法似乎是某种Applicative Functor和Promises应该是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
Run Code Online (Sandbox Code Playgroud)

知道(Promise a)是一个Functor,更容易理解为什么是Monad.

lef*_*out 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
Run Code Online (Sandbox Code Playgroud)

等等.


bhe*_*ilr 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
Run Code Online (Sandbox Code Playgroud)

这是否符合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))
Run Code Online (Sandbox Code Playgroud)

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

接下来,看看你是否可以编写ApplicativeMonad实例并证明它们符合各自的法律.如果你可以编写一个实例,那么你的数据类型是a Monad,而不管是哪个Future类.

  • 证明法律很难.构造`Promise f`和`Either(Maybe f)`之间的同构,并使用后者的`Monad`实例! (2认同)