Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
haskell连接多级monad_Haskell_Monads_Applicative - Fatal编程技术网

haskell连接多级monad

haskell连接多级monad,haskell,monads,applicative,Haskell,Monads,Applicative,我正在学习haskell,并尝试尽可能多地使用应用函子而不是monad。这是非常整洁和容易组成。然而,偶尔一些类型,如IO[IO[a]]或IO-Maybe-IO-Maybe-a会在代码中出现,这给我带来了很大的麻烦。显然,单子在这些场景中是不可避免的 我知道对于单级monad有一个简单的操作,比如join::m a->m a。对于多级单子有什么相似的吗?monad变形金刚里有什么吗 非常感谢 如果您注意到mn_u是一个monad转换器,那么您可以定义此操作。当我们注意到IO可能a与MaybeT

我正在学习haskell,并尝试尽可能多地使用应用函子而不是monad。这是非常整洁和容易组成。然而,偶尔一些类型,如IO[IO[a]]或IO-Maybe-IO-Maybe-a会在代码中出现,这给我带来了很大的麻烦。显然,单子在这些场景中是不可避免的

我知道对于单级monad有一个简单的操作,比如join::m a->m a。对于多级单子有什么相似的吗?monad变形金刚里有什么吗

非常感谢

如果您注意到mn_u是一个monad转换器,那么您可以定义此操作。当我们注意到IO可能a与MaybeT IO a相同时,情况就是这样:然后我们只使用MaybeT的连接。我们可以在很大程度上做到这一点,因为事实上,可能和IO层特别好

另一方面,并非所有合成的单子都是单子变压器。特别是,IO[a]并不是真正的一个。我们希望有和加入看起来像

newtype ListT m a = ListT { runListT :: m (Maybe (a, ListT m a)) }

在这种情况下,我们可以将IO[a]转换为ListIO a,反之亦然,但这些操作并不是相互颠倒的。的确,IO[a]本身不是单子,不能加入。

单子一般不通勤,但您可以提供您需要的所有特定情况:

{-# LANGUAGE MultiParamTypeClasses #-}

import Control.Monad

class (Monad m, Monad n) => Swappable m n where
    swap :: m (n a) -> n (m a)

instance Swappable [] IO where
    swap = sequence

instance Swappable Maybe IO where
    swap  Nothing  = return Nothing
    swap (Just mx) = fmap return mx

cut :: Swappable m n => m (n (m a)) -> n (m a)
cut = liftM join . swap

squash :: Swappable m n => n (m (n (m a))) -> n (m a)
squash = (>>= cut)
例如:

x :: IO [IO [()]]
x = return $ map (\s -> putStrLn s >> return [()]) ["ab","c"]

y :: IO (Maybe (IO (Maybe ())))
y = return $ Just $ putStrLn "z" >> return (Just ())

main = squash x >> squash y
印刷品

ab
c
z
编辑

您可以通过提供可遍历的实例来避免定义新的typeclass。数据中有Maybe和[]的实例。可遍历:


简单的回答是,newtype ListT m a=ListT m[a]遵循其他类型的模式,这些类型成功地成为单子,但没有遵循一般m的规则本身。我有点不精确,例如列表m是单子,正好在[]和m通勤时,例如m[a]与[ma]同构。这是。还有一个问题,从更具操作性的角度来看,问题在于m[a]与我在回答中给出的列表不同,我将所有m效应整合到顶部。这意味着list effects和m-effects分批运行,而不是交织运行,这通常是满足monad transformer定律所必需的。如果您查看,您将看到流函数允许我们从ListT m a转换为m[a]。值得注意的是,此操作演示了如何将所有m效应一起粉碎的问题。正如我所指出的,它也会导致堆叠,因为这意味着你不能真正地将列表延迟地流式处理,所有的m效果都会同时被强制执行。我不确定,在今天早上的光线下,为什么我叫它stream,实际上我觉得它类似于zipList的情况,但不能证明/反驳monad定律。对于IO[IO[a]],目前我使用fmap序列将它们转换为IO[a]],然后执行join和fmap join。它将成为IO[a],但我认为它相当丑陋。这种机制完全分离IO和[]效应。只要您感兴趣的特定效果具有IO[a]~[IO a],例如效果通勤,它就可以工作。某些IO效果可能会出现这种情况,但您会注意到,您对结果列表的使用和现实世界中出现的效果将变得不同步。这在惰性IO的情况下最明显是糟糕的,它要么被IO上的连接和序列强制严格,要么由于资源利用率(例如文件句柄)不与列表使用相互转换而不确定。非常感谢!但我觉得这更像是另一个特殊的变压器实现。。。
import Data.Traversable as T
import Control.Monad

cut :: (Traversable t, Monad t, Monad m) => t (m (t a)) -> m (t a)
cut = liftM join . T.sequence

squash :: (Traversable t, Monad t, Monad m) => m (t (m (t a))) -> m (t a)
squash = (>>= cut)