我觉得我忽略了一些完全明显的东西但是使用无点符号来组成二元函数和一元函数的正确方法(如果有的话)是什么?例如,以下代码编译:
sortedAppend :: (Ord a) -> [a] -> [a] -> [a]
sortedAppend xs ys = sort $ xs ++ ys
但以下代码无法编译:
sortedAppend :: (Ord a) -> [a] -> [a] -> [a]
sortedAppend = sort . (++)
我们是否可以使用(++)
(按上面显示的顺序)撰写sort
?如果是这样,怎么样?
答案 0 :(得分:18)
我不认为任何这些解决方案(我的或其他解决方案)都很漂亮,但我更喜欢....
let sortedAppend = (sort .) . (++)
我更喜欢这个的原因是因为我很容易想到......如果忽略括号,你基本上需要为每个参数添加额外的(。)
f . g --one parameter
f . . g --two params
f . . . g --three params
这是有道理的,因为g x
返回一个带有N-1个输入的函数....
....但是那些需要它的人会让它变得如此丑陋......
((f .) .) . g
答案 1 :(得分:12)
你可以使用" owl-operator" (我认为有时也称为breast.operator):
Prelude> :t (.).(.)
(.).(.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
但是:我认为你不应该 - 你所写的内容非常易读 - 使用这个:
sortedAppend = ((.).(.)) sort (++)
不是IMO
PS:是的,你可以做到
(.:.) = (.).(.)
sortedAppend = sort .:. (++)
但仍然......不易消化
PPS:我刚刚发现这个运算符在名为pointless-fun ^^
的包中被定义为(.:)
答案 2 :(得分:10)
为了完整起见,让我们实际上以你的榜样为例,逐渐使它成为免费的。
首先,请记住(f . g) x = f (g x)
。然后是Eta-reduction (\x -> f x) ≡ f
。最后一个有用的东西是operator section。
使用这些规则我们可以这样:
sortedAppend xs ys = sort $ xs ++ ys -- original function
sortedAppend xs ys = sort (xs ++ ys) -- remove $
sortedAppend xs ys = sort ((++) xs ys) -- prefix application of ++
sortedAppend xs ys = (sort . ((++) xs)) ys -- definition of composition
sortedAppend xs = sort . (++) xs -- eta reduction
sortedAppend xs = (sort .) ((++) xs) -- operator section
sortedAppend xs = ((sort .) . (++)) xs -- definition of composition
sortedAppend = (sort .) . (++) -- eta reduction
答案 3 :(得分:8)
我认为我个人不建议为这样的事情添加依赖项,但也有
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d