我知道 r -> a
是 a
中的 Functor
,并且 fmap = (.)
为之。
这意味着当我使用 g::r -> a
执行 fmap f g
时,f
应用于 g
,只要后者被输入 r
类型的值。但是,如果 a
是函数类型,例如一元函数 b -> c
,然后将 f
应用于该函数(这是实际发生的情况)和应用 f
之间存在差异g
的最终结果(在某些情况下可能是理想的;不是吗?)。
我如何映射到 g
的最终结果?在这种情况下 g::r -> b -> c
看起来很简单,我可以 uncurry $ fmap f $ curry g
。但是,如果 c
也是一个函数类型呢?
或者换句话说,我如何映射到多变量函数的最终结果?一般而言,curry
/uncurry
技巧是否必要/可行?
(相关问题 here .)
从评论/回答中可以明显看出,我没有意识到我本质上是在问我几天前已经问过的同一个问题。可能因为我是如何来到这里的,所以对我来说并不明显。本质上,是什么让我问这个问题是另一个在我脑海中席卷而来的问题:
如果我可以使用 liftA2(&&)
、liftA2(||)
和类似组合一元谓词,我该如何组合二元谓词? 为了回答这个问题,我在 GHCi 中玩了一下,想出了这个
liftIntoBinaryFunc p = \q r -> curry $ (liftA2 p) (uncurry q) (uncurry r)
这将允许做这样的事情:
-- some binary predicate
distanceLE3 x y = 3 >= abs (x - y)
sameSign x y = ((==) `on` signum) x y
-- function to lift into binary functions
liftIntoBinaryFunc p = \q r -> curry $ (liftA2 p) (uncurry q) (uncurry r)
-- lifting && into binary functions to Bool
and' = liftIntoBinaryFunc (&&)
-- combining
pred = distance3 `and'` sameSign
-- using
p 3 18 -- False
p 3 1 -- True
p 3 (-1) -- False
但是,这个问题也概括为我如何组合任意(虽然常见)元数的谓词?,答案可能是相同的。
最佳答案
r -> b -> c
是 r -> (b -> c)
所以 (fmap . fmap) (f::c -> d) (g::r -> b -> c)::r -> b -> d
:
> foo :: (c -> d) -> (r -> (b -> c)) -> r -> (b -> d) ;
foo = fmap . fmap
foo :: (c -> d) -> (r -> b -> c) -> r -> b -> d
> bar :: (c -> d) -> (r -> (b -> (t -> c))) -> r -> (b -> (t -> d)) ;
bar = fmap . fmap . fmap
bar :: (c -> d) -> (r -> b -> t -> c) -> r -> b -> t -> d
但是您必须知道有多少嵌套级别,才能相应地组成fmaps
,或者使用其他recent question 中的方法。 .
关于haskell - 关于映射到多参数函数的最终结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66957099/