Cos*_*una 5 monads dictionary haskell applicative
我试着写一个类似于Data.Map.unionWith的函数,但可能会失败.原来的人使用了Maybe,这确实是Monad,所以monadic对我来说效果很好.但是我想知道它是否可以用Applicative重写,因为我用纯粹的fmap来满足unionWith的类型要求.或者使用Data.Map中的其他函数而不是unionWith?
{-# LANGUAGE RankNTypes #-}
import Control.Monad
import Data.Map
unionWithM :: (Monad m, Traversable t)
=> (forall a. (a -> a -> a)
-> t a
-> t a
-> t a
)
-> (v -> v -> m v)
-> t v
-> t v
-> m (t v)
unionWithM u f a b = sequenceA (u f' (pure <$> a) (pure <$> b))
where f' x y = join $ f <$> x <*> y
unionWithOriginal :: Ord k => (a -> a -> Maybe a) -> Map k a -> Map k a -> Maybe (Map k a)
unionWithOriginal f a b = sequenceA (unionWith f' (Just <$> a) (Just <$> b))
where f' x y = join $ f <$> x <*> y
Run Code Online (Sandbox Code Playgroud)
是的,你可以,但你需要一个中间数据结构.问题是你在应用函数之前包装了Map的值,这就是你f'的类型的原因m a -> m a -> m a.转变f为f'你需要的join,即Monad.诀窍是在联合之后应用函数.为此你可以使用(Maybe a, Maybe a)哪个有点乱,所以你可以使用这些数据类型.如果我们手动推出它你就得到了
data These a b = That a | This b | These a b
unionWith' f a b = let theses = unionWith These (That <$> a) (This <$> b)
in sequenceA (f' <$> theses)
where f' (That a) = pure a
f' (This b) = pure b
f' (These a b) = f a b
Run Code Online (Sandbox Code Playgroud)
如果您使用该these软件包,则可以将其简化为
unionWith'' f a b = sequenceA $ alignWith (these pure pure f) a b
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |