2012-01-19 6 views
17

多くの場合、私はこのようなパターンの機能を持っている:ハスケル - パターンマッチングシンタックスシュガーと

f :: a -> b 
f x = case x of 
    ... -> g ... 
    ... -> g ... 
    ... 
    ... -> g ... 
    where g = ... 

ほとんどこの場合のシンタックスシュガーがあります:

f :: a -> b 
f ... = g ... 
f ... = g ... 
... 
f ... = g ... 

残念ながら、私は」することができます私のwhereを添付してください:私は明らかにnot in scopeの束を得るでしょう。 gを別の関数にすることはできますが、それはうまくありません。私のモジュールの名前空間は、ユーティリティ関数で汚染されています。 回避策はありますか?

+4

をエクスポートするために 'G'は、このように名前空間の汚染は、独自のモジュール*内*唯一の問題です。 –

答えて

10

あなたの最初の例は全く悪くないと思います。構文上の唯一の重みは、であり、=の代わりに->です。後者は、各節の関数名を省略できるという事実によって相殺されます。確かに、dflemstrの提案されたgoヘルパー関数さえ構文的に重いです。

通常の関数節の構文と比べて少し矛盾していますが、これはおそらく良いことです:xが利用可能な範囲をより正確に視覚的に区切ります。

+0

関数を定義するための等式構文は、不要な仕掛けのようなものです。 –

10

いいえ、回避策はありません。そのような関数に複数の句がある場合、それらはwhere節を共有できません。あなたが本当にが何らかの理由で関数型を使用したい場合は...

f x = 
    go x 
    where 
    go ... = g ... 
    go ... = g ... 
    g = ... 

:あなたの唯一のオプションは、case文を使用するか、またはこのような何かを行うことです。

6
f = g . h -- h is most of your original f 
    where h ... = ... 
     h ... = ... 
     g = 
+0

私はOPが、gの式のいずれかのRHSのどこにでも出現する可能性がある(またはまったくない)問題に対する一般的な解を探していたと思います。 –

+1

ええ、私は質問があいまいであると感じ、まだ答えられていなかった場合の答えを出しました。 – dave4420

3

あなたの元々の解決策が最も唯一の回避策であるようです。構文的には、たとえライターでなくても、関数のパラメータの直接パターンマッチングより重くはありません。

しかし、あなたが必要とするのは、前提条件を確認するだけで、パターンマッチではない場合は、whereのスコープに自由にアクセスできるようにするガードについて忘れないでください。しかし、実際には私はあなたのcase of解決策で何も悪いことを見ません。 Haskellの2010年から

f :: a -> b 
f a 
    | a == 2 = ... 
    | isThree a = ... 
    | a >= 4 = ... 
    | otherwise = ... 
    where isThree x = x == 3 
5

、またはGHCとのあなたも行うことができます。

f x 
    | m1 <- x = g 
    | m2 <- x = g 
    ... 
    where g = 

いますが、gのパターンでバインド変数を使用することはできませんのでご注意。それはと同等です:

f x = let g = ... in case() of 
    () -> case x of 
      m1 -> g 
      _ -> case x of 
       m2 -> g 
       .... 
1

は、あなたが一貫して最も上gを使用することを想定し、全てではないが、case文の異なるブランチのために、それは安全ですか?

f :: a -> ba一部およびb(おそらくは多型)、gは必ずしも一貫aからcを抽出する方法がなければならないことを意味する形c -> d、いくつかの関数であると仮定して操作します。それをgetC :: a -> cと呼んでください。その場合、解決策はすべての場合にh . g . getCを単に使用することです。ここではh :: d -> bです。

しかし、になれない場合は、aから常にcが得られます。おそらくaの形式はf cであり、fFunctorです。次にfmap g :: f c -> f dを入力して、f dbに変換します。

ここでちょっとしたことがありますが、gがすべての支店に適用されているように見えたときに、最初に気が付いたのはfmapでした。

0

LambdaCaseで、あなたもこれを行うことができます:あなたが持っていない

{-# language LambdaCase #-} 

f :: a -> b 
f = \case 
    ... -> g ... 
    ... -> g ... 
    ... 
    ... -> g ... 
    where g = ...