haskell或适用于验证 [英] haskell Either and Validation Applicative

查看:60
本文介绍了haskell或适用于验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题来自适用于任何人和验证应用程序"部分,第17章中的适用"《从第一原理开始的Haskell编程》一书.

I have a question arising from the section "Either and Validation Applicative" of Chapter 17 "Applicative" of the book "Haskell Programming from first principles".

我做了以下代码:

data Validation err a =
  Failure err
  | Success a
  deriving (Eq, Show)
data Errors =
  DividedByZero
  | StackOverflow
  | MooglesChewedWires
  deriving (Eq, Show)
instance Functor (Validation e) where
  fmap _ (Failure x) = Failure x
  fmap f (Success y) = Success (f y)
instance Monoid e =>
  Applicative (Validation e) where
    pure = Success
    Failure e1 <*> Failure e2
      = Failure (e1 <> e2)
    Failure e <*> _ = Failure e
    _ <*> Failure e = Failure e
    Success f <*> Success r = Success (f r)
success :: Validation [Errors] Int
success = Success (+1)
  <*> Success (1::Int)
fail0 :: Validation [Errors] Int
fail0 = Success (+1)
  <*> Failure [StackOverflow::Errors]
-- this doesn't work:
fail1a :: Validation [Errors] Int
fail1a = Failure [StackOverflow::Errors]
  <*> Success (1)
-- this works:
fail1b :: Validation [Errors] b
fail1b = Failure [StackOverflow::Errors]
  <*> Success (1::Int)
fail2 :: Validation [Errors] Int
fail2 = Failure [MooglesChewedWires]
  <*> Failure [StackOverflow::Errors]
fail3 :: Validation [Errors] Int
fail3 = (Failure [StackOverflow::Errors]
  <*> Success (+1)) <*> (Failure [MooglesChewedWires]
  <*> Failure [StackOverflow::Errors])
fail4 :: Validation [Errors] Int
fail4 = fail1b <*> fail2

fail4 = fail1b< *>fail2 有效,但是如果我将其更改为:

fail4 = fail1b <*> fail2 works, but if I changed it to:

fail4 = fail1a< *>fail2

抛出错误:

Couldn't match type ‘Int’ with ‘Int -> Int’
  Expected type: Validation [Errors] (Int -> Int)
    Actual type: Validation [Errors] Int
• In the first argument of ‘(<*>)’, namely ‘fail1a’
  In the expression: fail1a <*> fail2

为什么会这样?与 fail1b 相比, fail1a 的唯一区别是,在其类型签名中包含了 Int 类型而不是 b ..

Why does this happen? The only difference that fail1a has compared with fail1b, is the inclusion of type Int in its type signature instead of b ..

推荐答案

之所以会发生这种情况,是因为< *> 的类型为 Applicative f =>f(a-> b)->f a->f b .

This happens because <*> has type Applicative f => f (a -> b) -> f a -> f b.

让我们看看 fail4 的定义:

fail4 :: Validation [Errors] Int
fail4 = fail1b <*> fail2

我们可以推断出 fail1b fail2 的预期类型:

We can deduce expected types of fail1b and fail2:

fail4 :: Validation [Errors] Int
fail4 =       fail1b          <*>          fail2
              +----+                       +---+
                 v                           v
expected:   f (a -> b)                      f a       (Applicative f)
                 v                           v
real:   Validation [Errors] b      Validation [Errors] Int
                 v
   Validation [Errors] (Int -> c)
                 v
  Validation [Errors] (Int -> Int)

因此,在这种情况下,键入 fail1b Validation [Errors] b 转到 Validation [Errors](Int-> Int)

So, in this case type Validation [Errors] b of fail1b turn to Validation [Errors] (Int -> Int).

但是,如果将 fail1b 替换为 fail1a ,则无法完成:

However if you replace fail1b to fail1a it can't be done:

fail4 :: Validation [Errors] Int
fail4 =       fail1a          <*>          fail2
              +----+                       +---+
                 v                           v
expected:   f (a -> b)                      f a       (Applicative f)
              (error)                        v
real: Validation [Errors] Int      Validation [Errors] Int

如果将运算符< *> 替换为 *> ,则可以解决此问题:

You can fix it if you replace operator <*> to *>:

fail4 :: Validation [Errors] Int
fail4 = fail1b *> fail2 -- or fail1a *> fail2

这篇关于haskell或适用于验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆