2011-10-05 67 views
4

考慮一下:如何簡化這個表達式?

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,但「相反」。我有這樣的感覺,有一個令人尷尬的簡單解決方案。我忽略了什麼?

+0

您是否關心效率或可讀性? – jmg

+1

主要可讀性 – Landei

+0

如果你問我,我發現第一個最具可讀性。也許是這樣寫的:map fromEnum。 zipWith(==)$「aaaa」「abaa」' –

回答

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" 
+0

謝謝,這正是我想要的。現在我只需要打坐就可以了... – Landei

+2

當我看這個例子時,我想知道爲什麼沒有類型爲'(a - > a - > b) - >(b - > c) - > a - > a - > c'的組合符合樣式從'Data.Function'開啓::(b - > b - > c) - >(a - > b) - > a - > a - > c'。 –

+3

您可以將其定義爲。:= fmap fmap fmap。 – fuz

3

沒有預定義的庫函數做的正是這種功能組成的,你想在這裏。但是,如果你經常使用結構,如在一個問題中,你可以定義這樣一個函數:

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

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

+1。可以更簡潔地定義爲:'g。:f =(g。)。 F'。 – missingfaktor

+3

也被稱爲「Scaramanga」或「胸部」組合器:'(。:) =(。)。 (。)' – Nefrubyr

1

我已經定義了以下兩種組合程序爲美化的(.)部分:

  1. (|.>):您可以閱讀以下定義,右圖爲f,右圖爲g

    (|.>) :: (b -> c) -> (a -> a' -> b) -> (a -> a' -> c) 
    f |.> g = (f .) . g 
    
  2. (<.|):你可以閱讀下面的定義爲,左片gf組成。

    (<.|) :: (a -> b -> c) -> (a' -> b) -> (a -> a' -> c) 
    f <.| g = (. g) . f 
    

箭頭的方向表示在該組合物正在發生的方向。在這兩個組合器中,第一個可以在您的示例中使用如下:

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