Applicative 风格的动作之间的通信
Communication between actions in Applicative style
Haskell设计模式,写这个例子:
(+) <$> Nothing <*> Just 10 <*> Just 20
证明应用风格的动作之间的交流有限。
问题是我无法在 ghci 中编译此示例,出现错误:
<interactive>:28: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) => Maybe b
示例错误。任何这些工作:
Prelude> (+) <$> Nothing <*> Just 10
Nothing
Prelude> (+) <$> Just 10 <*> Just 20
Just 30
Prelude> (+) <$> Just 20 <*> Nothing
Nothing
但是给出的那个没有,因为 (+)
只有两个参数。
将其用作 (+)<$>_<*>_<*>_
意味着编译器会尝试推断 (+)
具有三个参数的类型。好吧,这并非完全不可想象,因为 Haskell multi-argument 函数实际上是一个参数的函数产生另一个参数的函数产生...
所以,“two-argument 函数” a -> a -> a
原则上可以有更多的参数,如果你用一个函数类型实例化 a
本身。说,a ~ (Int -> Int)
,然后
(+) :: Num (Int -> Int) => (Int -> Int) -> (Int -> Int) -> Int -> Int
┗━━━━━━━━━━┛ ┗━━━━━━━━━━┛ ┗━┛
瞧,三个参数。问题是 Int -> Int
或更一般地 a->b
是 而不是 数字类型,即 Num (a -> b)
不是可以满足的约束,尽管有人可以想象可以写这样一个实例。
请注意,有时 Monoid (a,b)
可以 的约束是有意义的,GHC 确实允许它们,但您需要遵循建议并启用 FlexibleContexts
扩展名,方法是将 {-# LANGUAGE FlexibleContexts #-}
放在源文件顶部,或在 GHCi 中 :set -XFlexibleContexts
。在您的示例中,这根本没有帮助。
要将 (+)
应用于任意数字或参数,您可以将其折叠到列表中:
> :m +Data.List
> foldl1 (+) [0,10,20]
30
同样,您可以将 applicative-lifted 形式 (liftA2 (+) p q ≡ (+)<$>p<*>q
) 折叠到 Maybe-numbers:
的列表上
> :m +Control.Applicative
> foldl1 (liftA2(+)) [Nothing, Just 10, Just 20]
Nothing
> foldl1 (liftA2(+)) [Just 0, Just 10, Just 20]
Just 30
Haskell设计模式,写这个例子:
(+) <$> Nothing <*> Just 10 <*> Just 20
证明应用风格的动作之间的交流有限。
问题是我无法在 ghci 中编译此示例,出现错误:
<interactive>:28: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) => Maybe b
示例错误。任何这些工作:
Prelude> (+) <$> Nothing <*> Just 10
Nothing
Prelude> (+) <$> Just 10 <*> Just 20
Just 30
Prelude> (+) <$> Just 20 <*> Nothing
Nothing
但是给出的那个没有,因为 (+)
只有两个参数。
将其用作 (+)<$>_<*>_<*>_
意味着编译器会尝试推断 (+)
具有三个参数的类型。好吧,这并非完全不可想象,因为 Haskell multi-argument 函数实际上是一个参数的函数产生另一个参数的函数产生...
所以,“two-argument 函数” a -> a -> a
原则上可以有更多的参数,如果你用一个函数类型实例化 a
本身。说,a ~ (Int -> Int)
,然后
(+) :: Num (Int -> Int) => (Int -> Int) -> (Int -> Int) -> Int -> Int
┗━━━━━━━━━━┛ ┗━━━━━━━━━━┛ ┗━┛
瞧,三个参数。问题是 Int -> Int
或更一般地 a->b
是 而不是 数字类型,即 Num (a -> b)
不是可以满足的约束,尽管有人可以想象可以写这样一个实例。
请注意,有时 Monoid (a,b)
可以 的约束是有意义的,GHC 确实允许它们,但您需要遵循建议并启用 FlexibleContexts
扩展名,方法是将 {-# LANGUAGE FlexibleContexts #-}
放在源文件顶部,或在 GHCi 中 :set -XFlexibleContexts
。在您的示例中,这根本没有帮助。
要将 (+)
应用于任意数字或参数,您可以将其折叠到列表中:
> :m +Data.List
> foldl1 (+) [0,10,20]
30
同样,您可以将 applicative-lifted 形式 (liftA2 (+) p q ≡ (+)<$>p<*>q
) 折叠到 Maybe-numbers:
> :m +Control.Applicative
> foldl1 (liftA2(+)) [Nothing, Just 10, Just 20]
Nothing
> foldl1 (liftA2(+)) [Just 0, Just 10, Just 20]
Just 30