2016-09-09 6 views
0

私はちょうどユニにハスケルを学習し始めました。そして、それを遊んでいるうちに、私は把握できないような問題に遭遇しました。ハスケル関数の合成方法

import Data.List 
list = ["Hello", "world"] 

main = print $ intercalate " something " (reverse (map reverse list)) 

出力:

"dlrow something olleH" 

しかし、私はそれを試してみましたので、ドットの代わりに括弧で「メイン」関数を書きたい:

main = print $ intercalate " something " . reverse . map reverse list 
次のコードは、私に望ましい結果を提供します

ただし、これにより次のエラーが表示されます。

test.hs:5:54: error: 
    • Couldn't match expected type ‘a0 -> [[Char]]’ 
        with actual type ‘[[Char]]’ 
    • Possible cause: ‘map’ is applied to too many arguments 

これらの点は、角括弧とまったく同じ意味を持つと考えました。なぜ括弧は機能しますが、ドットはタイプ関連のエラーを出しますか?どんな助けでも大歓迎です!

答えて

3

ブラケットは機能の構成を意味するものではありません。彼らは単に "このサブ表現をグループ化する"ことを意味します。

c = f . g . h 
:これは、のように書くこともできた関数の合成 fとして、以下の定義 cgh

c x = f (g (h x)) 

:もちろん、あなたがそれらの機能組成物の連鎖を作るために使用することができます

したがって、あなたは書くことができ

main = print $ c list 
where c = intercalate " something " . reverse . map reverse 

しかし、再度cをインライン化すると、構文解析ルールが壊れないように注意する必要があります。関数アプリケーションが任意の中置演算子よりも厳密にバインドするため、その合成チェーンの右にlistを書くだけでは機能しません(.それは実際には最短の挿入演算子です)。私。、

intercalate " something " . reverse . map reverse list 

は実際に

(intercalate " something ") . (reverse) . (map reverse list) 

として解析しかし、それはあなたが欲しいものではありませんされています。 listが、最後の要素だけでなく、実際にはコンポジションチェーン全体の引数であることを確認する必要があります。それを行うための好ましい方法は、$演算子である:

intercalate " something " . reverse . map reverse $ list 

$最低 prevedenceを持っている、ので、これはまた

((intercalate " something ") . (reverse) . (map reverse)) (list) 

として解析され、すぐにmap reverselistに適用することができます - これだけでは間違っているわけではなく、結果はもうコンポジションチェーンの一部ではありません:

intercalate " something " . reverse $ map reverse list 
+0

この明確な説明に感謝します。 – Felix

2

.を使用する機能構成は、機能に別のパラメータがあることを意味します。あなたが代わりに以下を書いていたら、それはうまくいくでしょう。

main = print $ (intercalate " something " . reverse . map reverse) list 

その方法は、list値はかっこ内に構成関数のパラメータです。あなたの試みで

main = (print . intercalate " something " . reverse . map reverse) list 
main = print . intercalate " something " . reverse . map reverse $ list 

map reverse listは単一の式、中置の引数である:

+0

実際には多くの意味があります。本当にありがとう! – Felix

3

次のように関数合成の等価性が行く:

main = print (intercalate " something " (reverse (map reverse list))) 
main = print (intercalate " something " ((reverse . map reverse) list)) 
main = print ((intercalate " something " . (reverse . map reverse)) list) 
main = (print . (intercalate " something " . (reverse . map reverse))) list 

や、不要な括弧をドロップすることにより、 .演算子は機能しません。map reverse関数を作成してから、作成した関数全体をlist引数に適用するだけです。

+0

お返事ありがとうございましたBergiありがとうございました! – Felix