说我有接受相同参数的函数,并且我想测试它们的输出对于相同的输入是否等效。
f :: a -> b -> c
g :: a -> b -> c
f a b == g a b
如何将参数a和b打包在x中,这样我可以编写以下内容。
f x == g x
什么是最好的方法,而无需自己包装功能?
答案 0 :(得分:2)
要准确地完成 的唯一方法是使用uncurry
:
let
x = (a, b)
in uncurry f x == uncurry g x
(或uncurryN
用于N
参数。)
但是,您可以使用(->) x
的{{1}}实例(即,以Applicative
作为输入的函数)来隐式“扩展”参数,而不是将参数包装在元组中这两个函数的参数,因此至少您只需提及一次。此实例通常在无点代码中使用。
例如,使用专门用于此实例的x
:
liftA2
您将获得以下模式:
-- General type:
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
-- Specialised to ‘(->) x’ (using TypeApplications syntax):
liftA2 @((->) _) :: (a -> b -> c) -> (x -> a) -> (x -> b) -> (x -> c)
要提出更多参数,请添加另一个liftA2 h f g x
-- =
(h <$> f <*> g) x
-- =
h (f x) (g x)
或liftA2
:
… <$> … <*> …
所以在您这样的情况下:
liftA2 (liftA2 h) f g x y
-- =
(liftA2 h <$> f <*> g) x y
-- =
h (f x y) (g x y)
f, g :: Int -> Char -> Bool
f i c = chr i == c
g i c = i == ord c
(liftA2 . liftA2) (==) f g :: Int -> Char -> Bool
-- =
liftA2 (liftA2 (==)) f g
-- =
(\ x y -> f x y == g x y)
中的N
对应于功能的数量; liftAN
调用的数量与参数的数量相对应。