Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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 如何用自由的(或更自由的)单子对采取一元参数的操作进行编码?_Haskell_Monads_Free Monad_Monadplus - Fatal编程技术网

Haskell 如何用自由的(或更自由的)单子对采取一元参数的操作进行编码?

Haskell 如何用自由的(或更自由的)单子对采取一元参数的操作进行编码?,haskell,monads,free-monad,monadplus,Haskell,Monads,Free Monad,Monadplus,大多数一元函数采用纯参数并返回一元值。但也有一些需要一元论证,例如: mplus :: (MonadPlus m) => m a -> m a -> m a finally :: IO a -> IO b -> IO a forkIO :: m () -> m ThreadId -- | From Control.Monad.Parallel forkExec :: m a -> m (m a) 它们中的每一个似乎都提出了一个不同的问题,我无法掌

大多数一元函数采用纯参数并返回一元值。但也有一些需要一元论证,例如:

mplus :: (MonadPlus m) => m a -> m a -> m a

finally :: IO a -> IO b -> IO a

forkIO :: m () -> m ThreadId

-- | From Control.Monad.Parallel
forkExec :: m a -> m (m a)
它们中的每一个似乎都提出了一个不同的问题,我无法掌握一种通用的方法,如何使用免费单子对这些动作进行编码。

  • finally
    forkIO
    中,问题在于一元参数的类型与结果不同。但是免费的话,我们需要它们是相同的类型,因为
    ioa
    被编码类型的类型变量替换,比如
    data MyFunctor x=Finally x x
    ,它只编码
    ioa->ioa->ioa

    在本文中,作者使用
    Fork next
    来首先实现

    cFork :: (Monad m) => Thread m Bool
    cFork = liftF (Fork False True)
    
    fork :: (Monad m) => Thread m a -> Thread m ()
    
    然后用它来实现

    cFork :: (Monad m) => Thread m Bool
    cFork = liftF (Fork False True)
    
    fork :: (Monad m) => Thread m a -> Thread m ()
    
    其中输入和输出具有不同的类型。 但我不明白这是否是通过某种过程得出的,或者仅仅是为了这个特殊目的而产生的一个临时想法

  • mplus
    尤其令人困惑:一种像

    data F b = MZero | MPlus b b
    
    分布在
    >=
    上,a更复杂。也是免费的MonadPlus的本机实现

    在中,它通过添加

    data NonDetEff a where
      MZero :: NonDetEff a
      MPlus :: NonDetEff Bool
    
    为什么
    MPlus
    NonDetEff Bool
    而不是
    NonDetEff a
    ?有没有一种方法可以让它在
    Free
    中工作,我们需要的数据类型是一个函子,而不是使用

  • 对于
    forkExec
    我根本不知道如何继续

我只回答
Freer
monad部分。回想一下定义:

data Freer f b where
    Pure :: b -> Freer f b
    Roll :: f a -> (a -> Freer f b) -> Freer f b
现在

data NonDetEff a where
  MZero :: NonDetEff a
  MPlus :: NonDetEff Bool
我们可以定义

type NonDetComp = Freer NonDetEff
Roll
应用于
MPlus
时,
a
Bool
统一,第二个参数的类型是
Bool->NonDetEff b
,它基本上是一个元组:

tuplify :: (Bool -> a) -> (a, a)
tuplify f = (f True, f False)

untuplify :: (a, a) -> (Bool -> a)
untuplify (x, y) True  = x
untuplify (x, y) False = y
例如:

ex :: NonDetComp Int
ex = Roll MPlus $ Pure . untuplify (1, 2)
因此,我们可以为非确定性计算定义一个
MonadPlus
实例

instance MonadPlus NonDetComp where
    mzero       = Roll MZero Pure
    a `mplus` b = Roll MPlus $ untuplify (a, b)
并运行它们

run :: NonDetComp a -> [a]
run (Pure x)       = [x]
run (Roll MZero f) = []
run (Roll MPlus f) = let (a, b) = tuplify f in run a ++ run b

在我看来,实现不是取决于函数的类型,而是取决于它的语义。“但我不明白这是否是使用某种过程得出的。”我认为这里的“过程”只是对你的领域进行了适当的建模。例如,我认为如果您首先尝试对“最通用”的异常函数(
throw
catch
?)进行编码,
finally
的编码将更加明显。最后,
的类型与
@user2407038的类型相同。我理解你的意思。但我对“机械地对整个接口进行编码,让解释器担心实现细节”的方法感兴趣。