Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/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
Loops 如果MonadPlus是;发电机“;类,那么“类”是什么;“消费者”;上课?_Loops_Haskell_Category Theory_Haskell Pipes_Monadplus - Fatal编程技术网

Loops 如果MonadPlus是;发电机“;类,那么“类”是什么;“消费者”;上课?

Loops 如果MonadPlus是;发电机“;类,那么“类”是什么;“消费者”;上课?,loops,haskell,category-theory,haskell-pipes,monadplus,Loops,Haskell,Category Theory,Haskell Pipes,Monadplus,管道可以分为两部分:发电机部分(产量)和用户部分(等待) 如果有一个管道只使用它的生成器的一半,并且只返回()(或从不返回),那么它可以表示为“列表正确完成”。事实证明,MonadPlus可以用来表示像ListDone right这样的任何东西 请注意,您可以只使用transformers依赖项构建任何ListT(而不仅仅是管道中的一个)。例如,下面是如何实现Pipes.Prelude.stdinLn的ListT模拟: -- stdinLn :: ListT IO String stdinLn

管道可以分为两部分:发电机部分(
产量
)和用户部分(
等待

如果有一个
管道
只使用它的生成器的一半,并且只返回
()
(或从不返回),那么它可以表示为“
列表
正确完成”。事实证明,
MonadPlus
可以用来表示像ListDone right这样的任何东西

请注意,您可以只使用transformers依赖项构建任何
ListT
(而不仅仅是管道中的一个)。例如,下面是如何实现
Pipes.Prelude.stdinLn的
ListT
模拟:

-- stdinLn :: ListT IO String
stdinLn :: (MonadTrans t, MonadPlus (t IO)) => t IO String
stdinLn = do
    eof <- lift isEOF
    if eof
        then mzero
        else do
            str <- lift getLine
            return str `mplus` stdinLn
--stdinLn::ListT IO字符串
stdinLn::(MonadTrans t,MonadPlus(tio))=>tio字符串
stdinLn=do

eof我认为答案不是将“generator-like”类型类双重化,而是使用一个简单的
类别
实例来扩展它,该实例相当于
管道的
/
(>~)
类别

不幸的是,无法安排类型变量使其满足所有三个类型类(
MonadPlus
MonadTrans
、和
Category
),因此我将定义一个新的类型类:

{-# LANGUAGE KindSignatures #-}

import Control.Monad
import Control.Monad.Trans.Class

class Consumer (t :: * -> (* -> *) -> * -> *) where
    await :: t a m a
    (>~)  :: t a m b -> t b m c -> t a m c
printer :: (Show a, Monad (t a IO), MonadTrans (t a), Consumer t) => t a IO r
printer = do
    a <- await
    lift (print a)
    printer
{-
printer :: Show a => Consumer a IO r
printer = do
    a <- await
    lift (print a)
    printer
-}

cat :: (MonadPlus (t a m), Consumer t) => t a m a
cat = await `mplus` cat
{-
cat :: Monad m => Pipe a a m r
cat = do
    a <- await
    yield a
    cat
-}

debug :: (Show a, MonadPlus (t a IO), MonadTrans (t a), Consumer t) => t a IO a
debug = do
    a <- await
    lift (print a)
    return a `mplus` debug
{-
debug :: Show a => Pipe a a IO r
debug = do
    a <- await
    lift (print a)
    yield a
    debug
-}

taker :: (Consumer t, MonadPlus (t a m)) => Int -> t a m a
taker 0 = mzero
taker n = do
    a <- await
    return a `mplus` taker (n - 1)
{-
taker :: Monad m => Int -> Pipe a a m ()
taker 0 = return ()
taker n = do
    a <- await
    yield a
    taker (n - 1)
-}
此类型类别的规则为类别规则:

await >~ f = f

f >~ await = f

(f >~ g) >~ h = f >~ (g >~ h)
然后,一旦您有了这个额外的类型类,您就可以同时实现
Consumer
s和
Pipe
s:

{-# LANGUAGE KindSignatures #-}

import Control.Monad
import Control.Monad.Trans.Class

class Consumer (t :: * -> (* -> *) -> * -> *) where
    await :: t a m a
    (>~)  :: t a m b -> t b m c -> t a m c
printer :: (Show a, Monad (t a IO), MonadTrans (t a), Consumer t) => t a IO r
printer = do
    a <- await
    lift (print a)
    printer
{-
printer :: Show a => Consumer a IO r
printer = do
    a <- await
    lift (print a)
    printer
-}

cat :: (MonadPlus (t a m), Consumer t) => t a m a
cat = await `mplus` cat
{-
cat :: Monad m => Pipe a a m r
cat = do
    a <- await
    yield a
    cat
-}

debug :: (Show a, MonadPlus (t a IO), MonadTrans (t a), Consumer t) => t a IO a
debug = do
    a <- await
    lift (print a)
    return a `mplus` debug
{-
debug :: Show a => Pipe a a IO r
debug = do
    a <- await
    lift (print a)
    yield a
    debug
-}

taker :: (Consumer t, MonadPlus (t a m)) => Int -> t a m a
taker 0 = mzero
taker n = do
    a <- await
    return a `mplus` taker (n - 1)
{-
taker :: Monad m => Int -> Pipe a a m ()
taker 0 = return ()
taker n = do
    a <- await
    yield a
    taker (n - 1)
-}
然后,任何库都可以为包装在
使用者
newtype中的类型实现一个
类别
实例

然后,无论何时使用
wait
(>~)
,您都会得到这样的约束:


我会认为这类似于
FoldM
,但我没有想太多。也许是吧?这不是我想要的,但我确实想提到
类别(消费者t m)
的想法非常酷。