2016-07-24 1 views
2

私はハスケルを学んでいます。これは簡単な例ですが、次の例でlambda関数内でパターンマッチングを使用できない理由を理解したいと思います(filterfoldの 'function running、filterfold'がランタイムエラーをもたらす理由)。ラムダのパターンマッチング

-- Runs 
filterfold' :: (a -> Bool) -> [a] -> [a] 
filterfold' p zs = foldr (\y zs -> if (p y) then y:zs else zs) [] zs 

-- Runtime error: Non-exhaustive patterns in lambda 
filterfold :: (a -> Bool) -> [a] -> [a] 
filterfold p (z:zs) = foldr (\y (z:zs) -> if (p y) then y:(z:zs) else (z:zs)) [] (z:zs) 

答えて

4

あなたはそれを使用することができますが、コンパイラがわかりますよう、あなたはケース

(入力が[]時)あなたはz:zsを言うならば、それは、入力リストでこのパターンに一致するようにしようと参照が欠落しています - あなたならば

  • 入力[1,2,3] = 1:[2,3](技術的には、リスト・データ型の異なるコンストラクタに基づいています)

ので、実行時にそれは知ることができません、あなたはz=1zs=[2,3]

  • を取得しますが、入力[]あなたはzzsz:zs = []ように得ることができないとき[]を見てこのケース/パターンを処理する方法と例外をスローします。

    あなたはあなたの例をよく見ると、あなたが実際に(zまたはzsを意味する - あなただけの再z:zsとしてそれらを使用)とにかく部品を使用しないことを確認する必要がありので、私はそれをよりよく

    を行う方法を伝えることはできません

    ... = foldr (\ x zs = case zs of 
             z:zs -> ... 
    

    またはあなたはそれが少し短くするLambdaCase拡張子を使用することができますラムダの内部表現 - とにかくあなたはcaseを使用することができます。

  • +0

    したがって、filterfold関数の引数のzsは範囲にありますが、filterfoldの 'z'を使用する代わりに、ラムダの内部でパターンマッチングを実行しようとしますか? – Daniel

    +1

    はいラムダ内の 'z'と' zs'は異なるものです( 'foldr'はそれらを提供します) - なぜlambda-argumentsのパラメータ/引数名を再使用すべきでないのですか?あなたのラムダは一度外側のスコープから隠すでしょう - もし 'filterfold'の外側のスコープから' z'と 'zs'を(再)使いたいなら' foldr(\ y ys - > ...) '(あるいは' p'、 'z'、' zs'、 'y';と違う名前であれば) – Carsten

    +0

    ですが、実際には2番目の引数が必要ないあなたが 'foldr'に与えている'関数 '(ラムダ)がなければ、リストの' head'にしか作用しないので、おそらく 'foldr'は必要ありません。 'foldr'の引数 – Carsten

    関連する問題