我在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。
答案 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?由于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))
所以是的,它确实符合Functor法则。
接下来,看看您是否可以编写Applicative
和Monad
个实例并证明它们符合相应的法律。如果您可以编写一个实例,那么您的数据类型为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