Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/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
Haskell 使用typeclass free monad重新绑定do表示法_Haskell_Monads_Typeclass_Do Notation - Fatal编程技术网

Haskell 使用typeclass free monad重新绑定do表示法

Haskell 使用typeclass free monad重新绑定do表示法,haskell,monads,typeclass,do-notation,Haskell,Monads,Typeclass,Do Notation,可以使用显式字典传递重新绑定(>>=)并返回monad,如下所示: {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RebindableSyntax #-} module Lib where import Prelude hiding ((>>=), return) data MonadDict m = MonadDict { bind :: forall a b. m a -> (a -> m b) -> m b ,

可以使用显式字典传递重新绑定(>>=)并返回monad,如下所示:

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}

module Lib where

import Prelude hiding ((>>=), return)

data MonadDict m = MonadDict {
  bind :: forall a b. m a -> (a -> m b) -> m b ,
  ret :: forall a. a -> m a }

(>>=) :: (MonadDict m -> m a) -> (a -> (MonadDict m -> m b)) -> (MonadDict m -> m b)
return :: a -> (MonadDict m -> m a)

monadDictIO :: MonadDict IO

usage = let
  monadicCode = do
    ln <- const getLine 
    const . putStrLn $ ln
  in monadicCode monadDictIO
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE RecordWildCards #-}

module Lib where
import Prelude hiding(return, fail, (>>=), (>>))

data MonadDict m = MonadDict
    { (>>=)  :: forall a b. m a -> (a -> m b) -> m b
    , (>>)   :: forall a b. m a -> m b -> m b
    , return :: forall a. a -> m a
    , fail   :: forall a. String -> m a
    }

monadDictIO :: MonadDict IO
monadDictIO = ...

foo :: MonadDict m -> String -> m ()
foo = ...

usage = let
    monadicCode m@MonadDict{..} = do
        ln <- getLine
        putStrLn ln
        foo m ln
    in monadicCode monadDictIO
{-#语言等级}
{-#语言可重新绑定语法#-}
模块库在哪里
导入前奏隐藏((>>=),返回)
数据MonadDict m=MonadDict{
绑定::对于所有AB.MA->(a->MB)->MB,
ret::对于所有a.a->m a}
(>>=)::(单体m->MA)->(a->(单体m->MB))->(单体m->MB)
return::a->(MonadDict m->ma)
monaddicio::MonadDict IO
用法=let
monadicCode=do
ln你可以这样做:

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}

module Lib where

import Prelude hiding ((>>=), return)

data MonadDict m = MonadDict {
  bind :: forall a b. m a -> (a -> m b) -> m b ,
  ret :: forall a. a -> m a }

(>>=) :: (MonadDict m -> m a) -> (a -> (MonadDict m -> m b)) -> (MonadDict m -> m b)
return :: a -> (MonadDict m -> m a)

monadDictIO :: MonadDict IO

usage = let
  monadicCode = do
    ln <- const getLine 
    const . putStrLn $ ln
  in monadicCode monadDictIO
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE RecordWildCards #-}

module Lib where
import Prelude hiding(return, fail, (>>=), (>>))

data MonadDict m = MonadDict
    { (>>=)  :: forall a b. m a -> (a -> m b) -> m b
    , (>>)   :: forall a b. m a -> m b -> m b
    , return :: forall a. a -> m a
    , fail   :: forall a. String -> m a
    }

monadDictIO :: MonadDict IO
monadDictIO = ...

foo :: MonadDict m -> String -> m ()
foo = ...

usage = let
    monadicCode m@MonadDict{..} = do
        ln <- getLine
        putStrLn ln
        foo m ln
    in monadicCode monadDictIO
{-#语言等级}
{-#语言可重新绑定语法#-}
{-#语言记录通配符}
模块库在哪里
导入前奏隐藏(返回、失败、(>>=)、(>>))
数据MonadDict m=MonadDict
{(>>=)::对于所有a b.m a->(a->m b)->m b
,(>>)::对于所有工商管理硕士->工商管理硕士->工商管理硕士
,return::for all a.a->m a
,失败::对于所有a.字符串->m a
}
monaddicio::MonadDict IO
单加性=。。。
foo::MonadDict m->String->m()
foo=。。。
用法=let
单子码m@MonadDict{..}=do

ln简短且不正确的答案是将
MonadDict m
参数从第二个参数的返回类型中删除到
(>>=)

但这并不能真正解决所有语法问题。如果有人有一个类型为
Monad m=>a->mb
的现有箭头,并通过显式字典,则该箭头的类型为
a->(MonadDict m->mb)
,并且不能用作
(>>=)
的第二个参数。如果有一个函数
drop::(MonadDict m->mb)->mb
使其与第二个参数兼容,那么就没有理由传递
MonadDict
s


您正在重新设计转换器,以读取
MonadDict m

newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
每次使用
const
时,它相当于将
ma
提升到
ReaderT(MonadDict m)ma
。如果您使用
lift
而不是
const
编写示例,您的示例看起来就不会那么陌生了

usage = let
  monadicCode = do
    ln <- lift getLine 
    lift . putStrLn $ ln
  in monadicCode monadDictIO
如果你给它自己的类型,你可以为它配备一个独立于底层
m
Monad
实例,并且省去
rebindabletsyntax

newtype ReadMD m a = ReadMD {runReadMD :: MonadDict m -> m a}

instance Functor (ReadMD f) where
    fmap = liftM

instance Applicative (ReadMD f) where
    pure = return
    (<*>) = ap

instance Monad (ReadMD m) where
    m >>= k = ReadMD $ \d@MonadDict { bind = bind } -> bind (runReadMD m d) (\a -> runReadMD (k a) d)
    return a = ReadMD $ \d@MonadDict { ret = ret } -> ret a
newtype ReadMD m a=ReadMD{runReadMD::MonadDict m->m a}
实例函子(ReadMD f),其中
fmap=liftM
实例应用程序(ReadMD f),其中
纯=返回
()=ap
实例Monad(ReadMD m)其中
m>>=k=ReadMD$\d@MonadDict{bind=bind}->bind(runReadMD m d)(\a->runReadMD(ka)d)
返回a=ReadMD$\d@MonadDict{ret=ret}->ret a

你肯定会想要更像
(>>=)::MonadDict m->ma->(a->mb)->mb
,或者如果你有三个不同的字典,你打算怎么做?@DanielWagner我只使用过一次看到
用法部分,我在最后传递字典通常是简单的不变量,比如“我只传递一个”请打字员帮你检查是件好事。我建议的类型是要求它这样做的一种方式。@DanielWagner您如何将多个
单子添加m
s传递给
>=
;只有一个是公开的,即最后的
MonadDict m
参数;只要
>>=
将参数传递给该读卡器并传递给其他两个读卡器,那么相同的字典将用于所有3个读卡器
(>>=)
的类型与
ReaderT(MonadDict m)m
的前奏曲
(>>=)
相同,但有不同的实现。@Cirdec啊,你说得对:我完全误读了类型签名!有趣。事实证明,这甚至适用于
-XRecordWildCards
:如果您分别调用
bind
字段
>=
>
,您只需使用
monadicCode monadict{..}=do…
。这是否是一个好主意,我不太确定,但所有这一切肯定是有趣的。