haskell Either 和 Validation Applicative
haskell Either and Validation Applicative
我有一个问题来自“Haskell 从第一原则编程”一书的第 17 章“应用程序”的“Either and Validation Applicative”部分。
我做了以下代码:
data Validation err a =
Failure err
| Success a
deriving (Eq, Show)
data Errors =
DividedByZero
| Whosebug
| 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 [Whosebug::Errors]
-- this doesn't work:
fail1a :: Validation [Errors] Int
fail1a = Failure [Whosebug::Errors]
<*> Success (1)
-- this works:
fail1b :: Validation [Errors] b
fail1b = Failure [Whosebug::Errors]
<*> Success (1::Int)
fail2 :: Validation [Errors] Int
fail2 = Failure [MooglesChewedWires]
<*> Failure [Whosebug::Errors]
fail3 :: Validation [Errors] Int
fail3 = (Failure [Whosebug::Errors]
<*> Success (+1)) <*> (Failure [MooglesChewedWires]
<*> Failure [Whosebug::Errors])
fail4 :: Validation [Errors] Int
fail4 = fail1b <*> fail2
fail4 = fail1b <*> fail2
有效,但如果我将其更改为:
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
为什么会这样? fail1a
与 fail1b
相比的唯一区别是在其类型签名中包含类型 Int
而不是 b
..
发生这种情况是因为 <*>
的类型为 Applicative f => f (a -> b) -> f a -> f b
。
让我们看看fail4
的定义:
fail4 :: Validation [Errors] Int
fail4 = fail1b <*> fail2
我们可以推断出 fail1b
和 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)
。
但是,如果将 fail1b
替换为 fail1a
,则无法完成:
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
将运算符 <*>
替换为 *>
:
即可解决
fail4 :: Validation [Errors] Int
fail4 = fail1b *> fail2 -- or fail1a *> fail2
我有一个问题来自“Haskell 从第一原则编程”一书的第 17 章“应用程序”的“Either and Validation Applicative”部分。
我做了以下代码:
data Validation err a =
Failure err
| Success a
deriving (Eq, Show)
data Errors =
DividedByZero
| Whosebug
| 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 [Whosebug::Errors]
-- this doesn't work:
fail1a :: Validation [Errors] Int
fail1a = Failure [Whosebug::Errors]
<*> Success (1)
-- this works:
fail1b :: Validation [Errors] b
fail1b = Failure [Whosebug::Errors]
<*> Success (1::Int)
fail2 :: Validation [Errors] Int
fail2 = Failure [MooglesChewedWires]
<*> Failure [Whosebug::Errors]
fail3 :: Validation [Errors] Int
fail3 = (Failure [Whosebug::Errors]
<*> Success (+1)) <*> (Failure [MooglesChewedWires]
<*> Failure [Whosebug::Errors])
fail4 :: Validation [Errors] Int
fail4 = fail1b <*> fail2
fail4 = fail1b <*> fail2
有效,但如果我将其更改为:
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
为什么会这样? fail1a
与 fail1b
相比的唯一区别是在其类型签名中包含类型 Int
而不是 b
..
发生这种情况是因为 <*>
的类型为 Applicative f => f (a -> b) -> f a -> f b
。
让我们看看fail4
的定义:
fail4 :: Validation [Errors] Int
fail4 = fail1b <*> fail2
我们可以推断出 fail1b
和 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)
。
但是,如果将 fail1b
替换为 fail1a
,则无法完成:
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
将运算符 <*>
替换为 *>
:
fail4 :: Validation [Errors] Int
fail4 = fail1b *> fail2 -- or fail1a *> fail2