在Haskell中应用多个参数的更简单方法

时间:2015-06-11 22:31:46

标签: haskell functional-programming composition functor applicative

给定类型为f的值:: Applicative f => f (a -> b -> c),将参数映射到内部函数的最佳方法是什么。

到目前为止,我发现了以下内容:

(\x -> x a b) <$> f

(flip ($ a) b) <$> f

($ b) <$> ($ a) <$> f

我想我的问题是为什么Haskell没有:: a -> b -> (a -> b -> c) -> c函数。或者是吗?

2 个答案:

答案 0 :(得分:5)

Applicative类有<*>运算符(通常发音为&#34; ap&#34;,对于大多数Control.Monad.ap来说相当于Monad)结合<$>运算符(本身只是fmap的中缀别名)可以编写类似

的代码
-- f :: a -> b -> c
-- fa :: Applicative f => f a
-- fb :: Applicative f => f b
f <$> fa <*> fb :: Applicative f => f c

如果您需要应用纯参数,请使用pure类的Applicative方法:

-- f :: a -> b -> c
-- a :: a
-- b :: b
f <$> pure a <*> pure b :: Applicative f => f c

一个例子可能是

sumOfSquares :: Num a => a -> a -> a
sumOfSquares a b = a * a + b * b

> sumOfSquares <$> Just 1 <*> Just 2
Just 5
> sumOfSquares <$> Just 1 <*> Nothing
Nothing
> sumOfSquares <$> pure 1 <*> pure 2 :: Maybe Int
5
> sumOfSquares <$> readLn <*> readLn :: IO Int
1<ENTER>
2<ENTER>
5

这里Applicative f => f (a -> b -> c)正在构建f <$>,所以如果您已经拥有类似

的内容
> let g :: IO (Int -> Int -> Int); g = undefined

然后您可以将其用作

> g <*> pure 1 <*> pure 2

<*>运算符的类型为

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

因此,如果您的函数的类型为x -> y -> z,然后是a ~ xb ~ y -> z,那么<*>的重复 ap 折叠(得到它?)将更多参数传递给包装函数。

答案 1 :(得分:2)

我们有

(<$>) :: Functor f => (a -> b) -> f a -> f b

但你想要相反的

(>$<) :: Functor f => f (a -> b) -> a -> f b

我们可以轻松定义:

(>$<) f a = ($a) <$> f

所以给出

f :: Functor f => f (a -> b -> c)
a :: a
b :: b

然后

f >$< a :: f (b -> c)
f >$< a >$< b :: f c

这不像<*>那样惯用,但它适用于所有Functor,而不仅仅是Applicative,这很好。