3

本「Real World Haskell」からHaskellを学んでいます。66 ページと 67 ページでは、次の例で case 式が示されています。

fromMaybe defval wrapped =
    case wrapped of 
        Nothing    -> defval
        Just value -> value

私は F# で同様のことを覚えていますが、(この本の前半で示したように) Haskell は関数を一連の方程式として定義できます。私の知る限り、Fシャープはできません。だから私はこれをそのような方法で定義しようとしました:

fromMaybe2 defval Nothing = defval
fromMaybe2 defval (Just value) = value

私はそれを GHCi にロードし、いくつかの結果を確認した後、同じであると確信しました。これは、方程式の場合になぜケース式が必要なのか疑問に思います。

  • より理解しやすい (それは数学です。なぜ を使用するのかcase something of、誰がそれを言うのですか?);
  • 冗長ではありません (2 対 4 行)。
  • 必要な構造化とシンタックス シュガーがはるかに少なくなります (->演算子である可能性があります。彼らが行ったことを見てください!)。
  • 必要な場合にのみ変数を使用します (wrappedスペースを占有するなどの基本的なケースでは)。

case 式の良い点は何ですか? それらは、似たような FP ベースの言語 (F# など) にあるという理由だけで存在するのでしょうか? 何か不足していますか?

編集:

@freyrsの回答から、コンパイラーがこれらをまったく同じにすることがわかります。したがって、方程式は常にケース式に変換できます (予想どおり)。次の質問は逆です。コンパイラとは逆のルートをたどり、let/where式を含む方程式を使用して任意のケース式を表現できますか?

4

6 に答える 6

4

-ddump-simpl -dsuppress-all2 つの関数は、Haskell でまったく同じ内部コード ( Core と呼ばれる) にコンパイルされ、フラグを ghcに渡すことでダンプできます。

変数名が少し難しそうに見えるかもしれませんが、実際には、上で書いたコードを明示的に型付けしただけのバージョンです。唯一の違いは、変数名です。

fromMaybe2
fromMaybe2 =
  \ @ t_aBC defval_aB6 ds_dCK ->
    case ds_dCK of _ {
      Nothing -> (defval_aB6) defval_aB6;
      Just value_aB8 -> (value_aB8) value_aB8
    }

fromMaybe
fromMaybe =
  \ @ t_aBJ defval_aB3 wrapped_aB4 ->
    case wrapped_aB4 of _ {
      Nothing -> (defval_aB3) defval_aB3;
      Just value_aB5 -> (value_aB5) value_aB5
    }
于 2013-12-24T18:47:35.477 に答える
1

追加された質問への答えはイエスですが、かなり醜いです。

case exp of
  pat1 -> e1
  pat2 -> e2
  etc.

エミュレートできると思います

let
  f pat1 = e1
  f pat2 = e2
  etc.
in f exp

f が exp、e1、e2 などでフリーでない限り。

于 2013-12-24T19:54:03.010 に答える