重新包装monad - 任何通用方式?

hps*_*use 13 monads haskell

给定两个monad,Monad m并且Monad n,我想转换m (n a)n (m a).但似乎是因为两者没有通用的方法(>>=)return交易只有一个单子类型,虽然(>>=)允许提取一个单子的内容,则必须收拾他们回到同一个单子类型,以便它可以是一个结果值.

但是,如果我们设置m为固定类型,则工作变得容易.以Maybe为例:

reorder :: (Monad n) => Maybe (n a) -> n (Maybe a)
reorder Nothing = return Nothing
reorder (Just x) = do
    x' <- x
    return $ Just x'
Run Code Online (Sandbox Code Playgroud)

或者列表:

reorder :: (Monad n) => [n a] -> n [a]
reorder [] = return []
reorder (x:xs) = do
    x'  <- x
    xs' <- reorder xs
    return (x':xs')
Run Code Online (Sandbox Code Playgroud)

不难看出,我们这里有一个模式.更明显的是,以某种Applicative方式编写它,它只不过是将数据构造函数应用于每个元素:

reorder (Just x) = Just <$> x
reorder (x:xs) = (:) <$> x <*> (reorder xs)
Run Code Online (Sandbox Code Playgroud)

我的问题是:是否已经存在用于描述此类操作的haskell类型类,或者我是否必须自己发明轮子?

我在GHC文档中进行了简短的搜索,发现没有什么对这个主题有用.

rei*_*erp 14

Data.Traversable提供您正在寻找的内容:

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
Run Code Online (Sandbox Code Playgroud)

GHC甚至为自动派生实例提供支持:

{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
import Data.Foldable
import Data.Traversable

data List a = Nil | Cons a (List a) 
  deriving(Functor, Foldable, Traversable)
Run Code Online (Sandbox Code Playgroud)


Ric*_* T. 5

快速搜索hoogle,(Monad m, Monad n) => m (n a) -> n (m a)向我展示了几个功能(大致)符合您正在寻找的签名:

  1. Data.Traversable.sequence :: (Traversable t, Monad m) => t (m a) -> m (t a);
  2. Data.Traversable.sequenceA :: Applicative f => t (f a) -> f (t a);
  3. Contro.Monad.sequence :: Monad m => [ma] - > m [a](也由...导出Prelude).

这两个[a]Maybe a是穿越的情况下,让你重新排序函数只是应用Data.Traversable.sequence.一个人可以写,例如:

ghci> (Data.Traversable.sequence $ Just (return 1)) :: IO (Maybe Int)
Just 1
it :: Maybe Int

ghci> (Data.Traversable.sequence $ Just ([1])) :: [Maybe Int]
[Just 1]
it :: [Maybe Int]

ghci> (Data.Traversable.sequence $ [Just 1]) :: Maybe [Int]
Just [1]
it :: Maybe [Int]
Run Code Online (Sandbox Code Playgroud)

但是请注意,具体的类声明是class (Functor t, Foldable t) => Traversable t,如果你看一下其他两个函数的类型,它看起来不像你正在寻找的可能是通用的方式为所有monad mn没有限制/前提条件.