如果我有一个包含在a -> b
中的函数(例如Applicative
类型)和一个可以应用于它的值(即上例中的a
类型的值),我可以按如下方式申请:
doSomething :: Applicative f => f (a -> b) -> a -> f b
doSomething wrappedFn arg = wrappedFn <*> (pure arg)
我发现自己做了很多。是否有一个标准的预定义运算符可以使这些代码更简洁,或者我是否需要自己定义一个?如果是后者,是否有传统名称?
答案 0 :(得分:6)
是否有一个标准的预定义运算符可以使这段代码更简洁......?
没有
...或者我需要自己定义一个吗?
是(除非您要导入外部包)。
如果是后者,是否有传统名称?
镜头中称为(??)
,有些人other names。根据镜头,它是flip
的广义变体,这是有道理的:
flip :: (a -> b -> c) -> b -> a -> c
(??) :: Functor f => f (b -> c) -> b -> f c
用f
替换((->) a
,flip
获得(??)
。因此,您可以将其称为广义翻转。
顺便说一句,您不需要Applicative
。 Functor
就够了:
gFlip :: Functor f => f (a -> b) -> a -> f b
gFlip f x = fmap ($x) f
一些例子:
ghci> gFlip [(+ 1),(* 2)] 2
[3, 4]
ghci> gFlip (++) "world" "hello"
"helloworld"
答案 1 :(得分:3)
实际上有一个中等知名的运算符版本,即(??)
from lens:
(??) :: Functor f => f (a -> b) -> a -> f b
请注意Functor
约束。事实证明,Applicative
并非必要,因为它可以定义为\f x -> ($ x) <$> f
。
(??)
的规范用例是函数functor,作为中缀flip
:
GHCi> execState ?? [] $ modify (1:)
[1]
在一般情况下,它完全符合您的要求:
GHCi> [negate] ?? 3
[-3]
(就个人而言,我仍然认为[negate] <*> pure 3
更具可读性,但是YMMV。)