如何简化这个表达式?

时间:2011-10-05 12:33:23

标签: haskell

考虑一下:

map fromEnum $ zipWith (==) "aaaa" "abaa"
-- [1,0,1,1]

在这里只有一步是很好的:

zipWith (\x y -> fromEnum (x == y)) "aaaa" "abaa"

现在我可以取消y

zipWith (\x -> fromEnum.(x ==)) "aaaa" "abaa"

但我没有消除x。当然有办法“欺骗”......

zipWith (curry (fromEnum . uncurry (==))) "aaaa" "abaa"

......但这看起来比原来的lambda更丑。

我寻找的功能与Data.Function.on有些相似,但“相反”。我觉得有一个令人尴尬的简单解决方案。我忽视了什么吗?

3 个答案:

答案 0 :(得分:7)

zipWith (\x -> fromEnum . (x ==)) "aaaa" "abaa"

可以写成

zipWith (\x -> (fromEnum .) (x ==)) "aaaa" "abaa"

可以写成

zipWith ((fromEnum .) . (==)) "aaaa" "abaa"

如果您发现这种可读性取决于我的口味。

编辑:另一个很好的方法是使用some combinators by Matt Hellige

zipWith ((==) $. id ~> id ~> fromEnum) "aaaa" "abaa"

答案 1 :(得分:3)

没有预定义的库函数可以完成您想要的这种函数组合。但是如果你经常使用像问题中那样的结构,你可以定义这样一个函数:

(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
g .: f = \x y -> g (f x y)

x = zipWith (fromEnum .: (==)) "aaaa" "abaa"

答案 2 :(得分:1)

我已经定义了以下两个组合器用于美化(.)的部分:

  1. (|.>):您可以阅读以下定义:右侧切片f,并使用g撰写。

    (|.>) :: (b -> c) -> (a -> a' -> b) -> (a -> a' -> c)
    f |.> g = (f .) . g
    
  2. (<.|):您可以阅读以下定义:左侧切片g,并使用f撰写。

    (<.|) :: (a -> b -> c) -> (a' -> b) -> (a -> a' -> c)
    f <.| g = (. g) . f
    
  3. 箭头方向表示组成发生的方向。在这两个组合器中,第一个可以在您的示例中使用,如下所示:

    zipWith (fromEnum |.> (==)) "aaaa" "abaa"