如何从Haskell中的函数中提取函数的一部分?

lmyy7pcs  于 2023-11-18  发布在  其他
关注(0)|答案(1)|浏览(129)

我尝试将(Either a b -> c)类型的函数作为参数,并根据(f, g)形式的变量类型传递它使用的方法f和g,但我不确定如何做到这一点。
在另一个相关的问题中,我也试图接受一个类型为(a -> (b, c))的函数,并以(a -> b, a -> c)的形式返回它的两个方法。但我真的不知道该使用哪个方法。我试着阅读了一下,但也许我不知道如何正确地描述这个问题。
如果你们中的任何人知道Haskell中这类东西具体属于哪一类,我会很感激,这样我就可以阅读它了。
考虑到我不知道该怎么做,我所做的一切都是胡说八道。

7gcisfzg

7gcisfzg1#

这两个问题是相似的。
对于第一个问题,你想最终得到一个a->c类型的函数。你是从一个Either a b -> c类型的函数开始的。所以你需要用一个a -> Either a b类型的函数组合输入函数(在右边)。你可以猜测,或者问Hoogle答案:这是Left构造函数为你做的。
b->c部分可以用完全相同的方法求解,所以我们最终得到:

getComponentFunctionsA :: (Either a b -> c) -> (a->c, b->c)
getComponentFunctionsA f = (f . Left, f . Right)

字符串
至于第二个问题,我们需要在 * 左侧 * 使用库提供的成对组件提取器fstsnd组合a -> (b, c)类型的输入函数。
这给了我们:

getComponentFunctionsB :: (a -> (b, c)) -> (a -> b, a -> c)
getComponentFunctionsB f = (fst . f, snd . f)

免积分版本:

在函数式编程中,有一种称为Point-free Programming (PFP)的编程风格,在这种风格中,你定义的新函数主要是旧函数的组合,并且不需要命名/使用任何输入变量。
这里我们似乎有一个很好的PFP案例。因此,如果我们想使用无点风格定义上述函数,我们可以通过从Control.Arrow模块导入中缀(&&&)操作符来实现,将其多态类型专门化为:

(&&&) :: (b -> c) -> (b -> d) -> (b -> (c, d))


我们的两个函数可以这样重写:

import  Control.Arrow((&&&))

getComponentFunctionsA :: (Either a b -> c) -> (a->c, b->c)
getComponentFunctionsA = (. Left)  &&&  (. Right)

getComponentFunctionsB :: (a -> (b, c)) -> (a -> b, a -> c)
getComponentFunctionsB = (fst .)  &&&  (snd .)


请注意,这段代码中没有任何变量名。

相关问题