给定两个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)
快速搜索hoogle,(Monad m, Monad n) => m (n a) -> n (m a)向我展示了几个功能(大致)符合您正在寻找的签名:
Data.Traversable.sequence :: (Traversable t, Monad m) => t (m a) -> m (t a);Data.Traversable.sequenceA :: Applicative f => t (f a) -> f (t 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 m而n没有限制/前提条件.
| 归档时间: |
|
| 查看次数: |
431 次 |
| 最近记录: |