与二元算子的组合?

gut*_*rie 8 haskell function-composition

我想做一些相当简单的事情; 我正在使用带有Data.Map insertWith的运算符(++),它工作正常,但我想消除创建的值中的重复,所以想要用nub组合它.

我试过(nub(++)),(nub $(++)),(nub.(++)),都无济于事,因为(++)的类型与预期的小块类型不匹配( [一个] ).

我当然可以定义一个辅助函数或一个lambda,但我认为可能有一个更清晰的组合.

请提示!

Mik*_*kov 10

你可以这样写

((nub .) .) (++)
Run Code Online (Sandbox Code Playgroud)

例:

Prelude Data.List> ((nub .) .) (++) [1,2,3] [3,4,5]
[1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

一般来说,你有

(f . ) g x = f (g x) 
((f . ) . ) g x y = f (g x y) 
(((f . ) . ) . ) g x y z = f (g x y z) 
((((f . ) . ) . ) . ) g x y z v = f (g x y z v)
...
Run Code Online (Sandbox Code Playgroud)

以下是此身份的推导((nub .) .):

(f . g) x = f (g x)

(nub .) :: Eq a1 => (a -> [a1]) -> a -> [a1] 
(nub .) = \g x -> (nub (g x))

((nub .) .) :: Eq a2 => (a -> a1 -> [a2]) -> a -> a1 -> [a2]
((nub .) .) = ((\g x -> (nub (g x))) .) = (\g' x' -> (\g x -> (nub (g x))) (g' x'))
            = \g' x' x -> (nub ((g' x') x))
Run Code Online (Sandbox Code Playgroud)

关于这个(和相关的)成语有一篇很好的文章,但它是俄语:-(


Rot*_*sor 6

你想要的似乎是二进制和一元函数的组合,如下所示:

compose :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
compose unary binary a b = unary (binary a b)
Run Code Online (Sandbox Code Playgroud)

而你要求一个无点版本(没有提及ab变量).让我们一个接一个地尝试消除它们.我们将从b以下事实开始f (g x) = f . g:

compose unary binary a = unary . binary a
Run Code Online (Sandbox Code Playgroud)

a是下一个.让我们首先考虑表达式:

compose unary binary a = ((.) unary) (binary a)
Run Code Online (Sandbox Code Playgroud)

并再次应用相同的组合规则:

compose unary binary = ((.) unary) . binary
Run Code Online (Sandbox Code Playgroud)

这可以进一步写成:

compose unary = (.) ((.) unary)
Run Code Online (Sandbox Code Playgroud)

甚至是

compose = (.) . (.)
Run Code Online (Sandbox Code Playgroud)

在这里,每个(.)'剥离'二进制函数的参数,你需要其中两个,因为函数是二进制的.:广义任何函子当这个成语是非常有用的fmap . fmap(注意,fmap是等同于.当功能被看作是一个仿函数).这允许你"剥离"任何仿函数,例如你可以写:

incrementResultsOfEveryFunctionInTwoDimentionalList :: [[String -> Integer]] -> [[String -> Integer]]
incrementResultsOfEveryFunctionInTwoDimentionalList = fmap . fmap . fmap $ (+1)
Run Code Online (Sandbox Code Playgroud)

所以,你的结果变成了:

(fmap . fmap) nub (++)
Run Code Online (Sandbox Code Playgroud)

编辑:

我想我找到了大脑试图重现的答案:Haskell函数组合算子类型(c→d)→(a→b→c)→(a→b→d)