关于应用程序的多个论点不起作用?

Tar*_*ing 1 monads haskell applicative

所以我正在尝试了解 monad、函子和应用程序。我创建了以下重命名的Maybe调用的镜像匹配Sometimes。(我这样做是为了了解这些东西)

data Sometimes a = Nope | Thing a deriving Show

instance Monad Sometimes where
    (Thing x) >>= f = f x
    Nope  >>= f = Nope
    return      = Thing

instance Applicative Sometimes where
      pure = Thing
      Nope <*> _ = Nope
      (Thing g) <*> mx = fmap g mx

instance Functor Sometimes where
     fmap _ Nope = Nope
     fmap g (Thing x) = Thing (g x)
Run Code Online (Sandbox Code Playgroud)

因此,当我执行以下操作时,它会起作用:

pure (1+) <*> (Thing 1)
> Thing 2

pure (+) <*> (Thing 1) <*> (Thing 1)
> Thing 2
Run Code Online (Sandbox Code Playgroud)

但如果我尝试三个添加它不起作用:

pure (+) <*> (Thing 1) <*> (pure 1) <*> (pure 1)

<interactive>:108:1: error:
    • Non type-variable argument in the constraint: Num (a -> b)
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall a b. (Num (a -> b), Num a) => Sometimes b
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?我希望应用前两个,然后将第三个应用于前两个的结果。我的书谈到了实施fmap0, fmap1, fmap2...是如何效率低下的,因此

... 对于具有任何所需数量参数的函数,可以根据具有以下类型的两个基本函数来构造: pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b

并进一步说明:

的典型用法pure<*>具有以下形式:

pure g <*> x1 <*> x2 <*> ... <*> xn
Run Code Online (Sandbox Code Playgroud)

因此,我期待它能够工作,但我显然在定义/使用Applicative.


我正在使用 Graham Hutton 所著的《在 Haskell SE 中编程》一书

Wil*_*sem 5

这不起作用的原因是因为(+)求和两个数字,而不是三个。

您可以创建一个对三个数字求和的函数,例如:

pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
Run Code Online (Sandbox Code Playgroud)

这给了我们:

Prelude> pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
Thing 3
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?我希望应用前两个,然后将第三个应用于前两个的结果。

没错,但是在应用前两个之后,这不再是一个函数,而是一个Num a => Sometimes a. 事实上,如果我们确定类型,我们会看到Thing (+) :: Num a => Sometimes (a -> a -> a)and Thing 1 :: Num b => Sometimes b,所以这意味着它Thing (+) <*> Thing 1有 type Num a => Sometimes (a -> a)

然后我们确定的类型Thing (+) <*> Thing 1 <*> Thing 1,因为Thing (+) <*> Thing 1有 type Num a => Sometimes (a -> a),最后一个Thing 1有 type Num c => Sometimes c,这意味着Thing (+) <*> Thing 1 <*> Thing 1有 type Num a => Sometimes a,但这不是一个函数,除非有一个Num类型是一个函数,这就是错误所说的。