从 Learn you a Haskell 创建 `Prob` 的应用实现

Create an Applicative implementation of `Prob` from Learn you a Haskell

问题描述

Haskell 自从 Haskell 出版以来,似乎发生了一些变化。创建 Monads 时,您不仅需要定义 Functor,现在还需要定义 Applicative 实现。

在本书的第 14 章中,在 "Making Monads" 部分,我们定义了一个 newtype Prob like...

newtype Prob a = Prob { getProb :: [(a, Rational)] } deriving Show

然后它的 Functor 实例...

instance Functor Prob where
  fmap f (Prob xs) = Prob $ map (\(x, p) -> (f x, p)) xs

然后本书继续为它定义 Monad 实例...

flatten :: Prob (Prob a) -> Prob a
flatten (Prob xs) = Prob $ concat $ map multAll xs
  where multAll (Prob innerxs, p) = map (\(x,r) -> (x,r*p)) innerxs

instance Monad Prob where
  return x = Prob [(x,1%1)]
  m >>= f = flatten (fmap f m)
  fail _ = Prob []

但是我得到一个错误...

• No instance for (Applicative Prob) arising from the superclasses of an instance declaration

• In the instance declaration for ‘Monad Prob’

我读到现在明确需要 Applicative 实例并创建了我的解决方案,想知道它是否正确?

目前正在尝试自己实现它

我的实现是...

instance Applicative Prob where
  pure x = Prob [(x, 1%1)]
  (Prob xs) <*> (Prob ys) = Prob ([(f y, p * q) | (f, p) <- xs, (y, q) <- ys])

我这样做是因为 <*> 的第一个参数可能类似于 Prob [((*3),1%2),((+1),1%2)] 所以看起来第一个参数中的每个函数都必须应用于第二个参数以及概率也必须以某种方式处理。

请求答案

这对我来说似乎是错误的,我不喜欢我在本书中的实现只是自动的并且不需要任何额外工作的情况下提取这样的概率。我想知道是否有更简单的方法来定义我创建的内容,或者即使这首先是错误的?我觉得可能有一个 fmap 隐藏在我的 Applicative 代码中的某个地方,但我太新了,无法自己找到它。

如果有这些缺失的实现的更新资源就更好了,但我还没有找到。

如果您有 mMonad 实例,您将免费获得 mApplicative 实例,由

定义
instance Applicative m where
    pure  = return
    (<*>) = ap

回想一下 ap 是由

定义的
ap mf mx = mf >>= \f -> x >>= f

或者,使用 do 表示法,

ap mf mx = do 
    { f <- mf
    ; x <- mx
    ; return (f x)
    }

ApplicativeMonad 的概括。在这种规范方式下,每个 Monad 也必须是 Applicative。现代 Haskell 通过为每个 Monad.

要求一个 Applicative 实例来强制执行此操作

LYAH 早在 Applicative 成为 Monad 的超级 class 之前就已发布。当时,classes 的定义类似于

 class Functor where
     ...

 class Functor f => Applicative f where
     ...

 class Functor m => Monad m where
     ...

现在,Applicative 已插入 FunctorMonad 之间:

 class Functor where
     ...

 class Functor f => Applicative f where
     ...

 class Applicative m => Monad m where
     ...

以前,您通常会根据现有 FunctorMonad 实例定义新的 Applicative 实例。现在,您倾向于根据 Functor 定义 Applicative,根据 Applicative.

定义 Monad