【问题标题】:Continuation abstraction延续抽象
【发布时间】:2016-03-28 03:37:17
【问题描述】:

在基于此article 的有关并发性的一般练习中。

我们有:

-- a is the result type on which after we continue
type Continuation a = a-> Action

type ContinuationPseudoMonad a = Continuation a -> Action
-- pseudoMonad because it will need Concurrent wrapper Monad:
-- so as to define bind operation and return operation on it

data Concurrent a = Concurrent (ContinuationPseudoMonad a)

所以Concurrent a 是一个monad,我们必须用它的两个强制性法则来实施,返回和绑定。

不幸的是,我找不到足够的词来更准确地定义 ContinuationPseudoMonad 的东西......如果我没有词,我的脑海中就缺乏抽象。

你会怎么称呼它?

有没有意思Continuation a -> Action而不是我尴尬无意义的ContinuationPseudoMonad

动作是:

data Action = Atom (IO Action)
            | Fork Action Action
            | Stop

【问题讨论】:

  • 您的问题是如何为Concurrent 定义return>>=,就像您在上面定义的那样?
  • 另外,有点错别字 - 我想你的意思是,data Concurrent a = Concurrent (ContinuationPseudoMonad a),因为data Concurrent a = Concurrent ContinuationPseudoMonad a 是一个错误。
  • 我根据您的陈述进行了相应的更正。问题是我没有成功地理解什么是`Continuation a -> Action'。这个抽象的名字会很棒。
  • 我认为唯一的词是 'monad without its newtype wrapper' (顺便说一下,newtypedata for Concurrent 更好,因为它不会在运行时添加额外的层表示Concurrent 构造函数)或“连续传递式函数”。
  • 我很佩服您对各个级别的描述性名称的渴望

标签: haskell abstraction


【解决方案1】:

您似乎正在寻找一些词汇,这是一个难以表达的问题。让我们将您拥有的内容分解为步骤,看看是否有帮助。

data Action = Atom (IO Action)
            | Fork Action Action
            | Stop

Action 是一个具有三个构造函数代数数据类型。它是一个 corecursive 数据类型,因为它是根据自身定义的。

type Continuation a = a -> Action

Continuation a 函数类型 a -> Action类型别名。这是contravariant functor 的示例,因为我们可以定义一个函数

contramap :: (a -> b) -> Continuation b -> Continuation a
contramap aToB bToAction = aToAction 
  where aToAction = \a -> bToAction (aToB a)

注意反转 - contramap 采用函数 a -> b 并创建函数 Continuation b -> Continuation a

type ContinuationPseudoMonad a = Continuation a -> Action

ContinuationPseudoMonad a 是函数类型的另一个类型别名,但由于Continuation a 也是函数类型,ContinuationPseudoMonad a高阶函数的类型,因为它需要一个函数作为论据。

ContinuationPseudoMonad a 也是一个仿函数,但它是一个协变仿函数,因为我们可以定义一个函数

fmap :: (a -> b) -> ContinuationPseudoMonad a -> ContinuationPseudoMonad b
fmap aToB aToActionToAction = bToActionToAction
  where bToActionToAction = \bToAction -> aToActionToAction (\a -> bToAction (aToB a))

【讨论】:

    【解决方案2】:

    很明显Concurrent aCont Action a 相同,其中Cont 是延续单子。下面是对延续的简单解释:

    1. 考虑函数f :: a -> b 用于某些任意类型ab。我们想将此函数转换为延续传递样式。我们如何做到这一点?
    2. 假设我们有一个延续k :: b -> r,它将f 的返回值作为输入,它本身返回一个任意类型的值r。在此之后,我们可以将f 转换为 CPS。
    3. g :: a -> (b -> r) -> rf的CPS版本函数。请注意,它需要一个附加参数(即延续 k)并返回应用于其输出 bk 的结果。

    让我们举一个实际的例子,其中f是谓词函数odd :: Int -> Bool

    odd :: Int -> Bool
    odd n = n `mod` 2 == 1
    

    这是用延续传递风格编写的相同函数:

    odd' :: Int -> (Bool -> r) -> r
    odd' n k = k (n `mod` 2 == 1)
    

    (Bool -> r) -> r 部分可以抽象为延续单子:

    data Cont r a = Cont { runCont :: (a -> r) -> r }
    
    odd' :: Int -> Cont r Bool
    odd' n = return (n `mod` 2 == 1)
    
    instance Monad (Cont r) where
        return a = Cont (\k -> k a)
        m  >>= f = Cont (\k -> runCont m (\a -> runCont (f a) k))
    

    请注意,对于某些任意类型 r,延续 k 的类型是 Bool -> r。因此,延续k 可以是任何将Bool 作为参数的函数。例如:

    cont :: Bool -> IO ()
    cont = print
    
    main :: IO ()
    main = odd' 21 cont
    

    但是,对于Concurrent,这个r 不是任意的。它已专门用于Action。实际上,我们可以将Concurrent定义为Cont Action的类型同义词如下:

    type Concurrent = Cont Action
    

    现在,我们不需要为Concurrent 实现Monad 实例,因为它与上面定义的Cont rMonad 实例相同。

    runConcurrent :: Concurrent a -> ContinuationPseudoMonad a
    runConcurrent (Concurrent g) = g
    
    instance Monad Concurrent where
        return a = Concurrent (\k -> k a)
        m  >>= f = Concurrent (\k -> runConcurrent m (\a -> runConcurrent (f a) k))
    

    请注意,在instance Monad Concurrent 的定义中,我们没有使用Action。这是因为 Concurrent = Cont ActionCont r 的 monad 实例透明地使用了 r

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 2011-10-30
      • 2012-10-14
      • 2018-08-12
      • 2010-10-14
      • 2012-05-08
      相关资源
      最近更新 更多