我在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.
是的,这是一个单子.最简单的方法是观察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)
等等.
你要做的是尝试实现实例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?由于案件PendingPromise
和BrokenPromise
身份始终是身份,我将其简洁排除:
-- 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法则.
接下来,看看你是否可以编写Applicative
和Monad
实例并证明它们符合各自的法律.如果你可以编写一个实例,那么你的数据类型是a Monad
,而不管是哪个Future
类.