关于映射到多参数函数的最终结果
About mapping on the eventual result of a multi-argument function
我知道 r -> a
是 a
中的 Functor
,并且 fmap = (.)
是它的
这意味着当我使用 g :: r -> a
执行 fmap f g
时,一旦 g
被赋予一个值,f
就会应用于 g
的结果类型 r
。但是,如果 a
是函数类型,例如一元函数 b -> c
,然后将 f
应用于该函数(这是实际发生的情况)和将 f
应用于 g
的最终结果(这在某些情况下可能是可取的;不是吗?)。
如何映射 g
的最终结果?在这种情况下 g :: r -> b -> c
似乎很容易,我可以 uncurry $ fmap f $ curry g
。但是如果 c
也是一个函数类型呢?
或者换句话说,如何映射到多变量函数的最终结果? curry
/uncurry
技巧 necessary/doable 一般吗?
(相关问题。)
从 comments/answers 可以明显看出,我没有意识到我本质上是在问我几天前已经问过的同一个问题。可能因为 我是如何 来到这里的,所以对我来说并不明显。本质上,是什么让我问这个问题是另一个在我脑海中席卷而来的问题:
如果我可以使用 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
但是,这个问题也概括为 我如何组合任意(虽然常见)元数的谓词?,答案可能是相同的。
如果您想接受 n 个参数然后应用 f
,您可以调用 fmap
n 次。所以,如果 g :: r -> b -> c
,那么
(fmap . fmap) f g
将 f
应用于类型 c
的值,该值由将 g
应用于两个参数而产生,而如果 h :: a -> b -> c -> d -> e -> f -> g
,则
a b c d e f
(fmap . fmap . fmap . fmap . fmap . fmap) f h
将 f
应用到类型 g
的值,该值是将 h
应用到 6 个参数的结果。
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.
的方法
我知道 r -> a
是 a
中的 Functor
,并且 fmap = (.)
是它的
这意味着当我使用 g :: r -> a
执行 fmap f g
时,一旦 g
被赋予一个值,f
就会应用于 g
的结果类型 r
。但是,如果 a
是函数类型,例如一元函数 b -> c
,然后将 f
应用于该函数(这是实际发生的情况)和将 f
应用于 g
的最终结果(这在某些情况下可能是可取的;不是吗?)。
如何映射 g
的最终结果?在这种情况下 g :: r -> b -> c
似乎很容易,我可以 uncurry $ fmap f $ curry g
。但是如果 c
也是一个函数类型呢?
或者换句话说,如何映射到多变量函数的最终结果? curry
/uncurry
技巧 necessary/doable 一般吗?
(相关问题
从 comments/answers 可以明显看出,我没有意识到我本质上是在问我几天前已经问过的同一个问题。可能因为 我是如何 来到这里的,所以对我来说并不明显。本质上,是什么让我问这个问题是另一个在我脑海中席卷而来的问题:
如果我可以使用 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
但是,这个问题也概括为 我如何组合任意(虽然常见)元数的谓词?,答案可能是相同的。
如果您想接受 n 个参数然后应用 f
,您可以调用 fmap
n 次。所以,如果 g :: r -> b -> c
,那么
(fmap . fmap) f g
将 f
应用于类型 c
的值,该值由将 g
应用于两个参数而产生,而如果 h :: a -> b -> c -> d -> e -> f -> g
,则
a b c d e f
(fmap . fmap . fmap . fmap . fmap . fmap) f h
将 f
应用到类型 g
的值,该值是将 h
应用到 6 个参数的结果。
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.