我一直在重用lambda表达式,例如
\x -> (f x, g x)
Run Code Online (Sandbox Code Playgroud)
我将相同的输入应用于两个函数并将结果封装在一对中.我可以编写一个捕获它的函数
combine :: (a -> b) -> (a -> c) -> a -> (b,c)
combine f g x = (f x, g x)
Run Code Online (Sandbox Code Playgroud)
现在上面的lambda表达式就是这样combine f g.我有两个问题.
sha*_*haf 12
Control.Arrow有这个功能(&&&).它有一个"更一般"的类型,不幸的是,这意味着Hoogle没有找到它(可能这应该被认为是Hoogle中的一个错误?).
你通常可以算这样的事情自动pointfree,其lambdabot在#haskell具有作为一个插件.
例如:
<shachaf> @pl combine f g x = (f x, g x)
<lambdabot> combine = liftM2 (,)
Run Code Online (Sandbox Code Playgroud)
凡liftM2与(r ->)实例Monad有型(a -> b -> c) -> (r -> a) -> (r -> b) -> r -> c.当然,根据您允许的原语,还有许多其他方法可以无点编写.
C. *_*ann 12
我很想知道是否有一个标准的库函数可以做到这一点我找不到.
由于类型类很容易错过,但请注意Control.Arrow.平原Arrow不能被涂上或涂抹,因此Arrow组合器必须是无点的.如果你专注于它们(->),你会发现你想要的是这个:
(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c')
Run Code Online (Sandbox Code Playgroud)
还有其他类似的函数,比如等效的操作Either,专门(->)看起来像这样:
(|||) :: (a -> c) -> (b -> c) -> Either a b -> c
Run Code Online (Sandbox Code Playgroud)
哪个是一样的either.
出于好奇,我想以无点的方式重写这个功能,但我遇到了很多麻烦.
既然你重复输入,你需要做的是pointfree的一些方法-最常见的方式是通过Applicative或Monad实例(->),例如.这本质上是一个隐式的内联monad,被拆分的参数是"环境"值.使用这种方法,成为,或成为,成为,并成为小号组合子.\f g -> (,) <$> f <*> gReaderjoin f xf x xpurereturnconstfmap(.)(<*>) \f g x -> f x (g x)
实际上有很多方法可以做到这一点.最常见的方法是使用以下(&&&)功能Control.Arrow:
f &&& g
Run Code Online (Sandbox Code Playgroud)
但是,通常你有更多的功能或需要将结果传递给另一个函数,在这种情况下使用applicative样式会更方便.然后
uncurry (+) . (f &&& g)
Run Code Online (Sandbox Code Playgroud)
变
liftA2 (+) f g
Run Code Online (Sandbox Code Playgroud)
如上所述,这可以与多个功能一起使用:
liftA3 zip3 f g h
Run Code Online (Sandbox Code Playgroud)