0

undefined についてはすでに質問しました。そして、そんなことはありえないので、これが役に立つ場合について説明します。しかし、質問は一般的であり、他の場合に役立つと思います。

ある文法のパーサーを書くときの状況を想像してみましょう。多くのデータ型によって実装された AST を定義しました。それぞれに一連のコンストラクターがあり、各コンストラクターには一連のパラメーターがあります。すべての型は Show から派生します。次に、再帰的な依存関係を持つ多くの関数を定義するパーサーの実現を書き始めます。

多くの関数があるため、モジュール全体をチェックなしで一度に書くのは困難です。ただし、関数の循環参照では、未完成のモジュールをコンパイルできません。この場合、必要な型の戻り値を期待しないフック関数を定義します。

で、ここで問題!関数は単純な型ではなく、コンストラクター内にコンストラクターを持つデータ コンストラクターを返さなければなりません。これはフック関数には難しすぎます。だから私はこれを行います:

parseHook _ = undefined

そして、結果データツリーに「未定義」がなくなるまで、すべてが単純です。この状況は開発段階で発生し、私が望むのはツリー構造だけであることを指摘したいと思います。もちろん、すべての型を「Maybe」でラップできますが、既存の型を変更したくありません。

英語は私の母国語ではないので、自分の考えを正しく表現できているかどうか確信が持てません. そのため、この状況の例を追加したいと思います。

data StructParam = StructParam Int Int
                 deriving Show 

data Struct1 = Struct1 Int Int StructParam Int Int Int Int StructParam
             deriving Show 

data Struct2 = Struct2 Int Int StructParam Int Int Int Int StructParam  
             deriving Show 

data Struct3 = Struct3_var1 Struct1 
             | Struct3_var2 Struct2
             deriving Show 

-- this hook is ok, but too long
parse1 _ = Struct1 1 2 (StructParam 3 4) 5 6 7 8 (StructParam 9 0)

-- this hook is short, but undefined
parse2 _ = undefined

-- complete function
rootParse 1 = Struct3_var1(parse1 1)    
rootParse 2 = Struct3_var2(parse2 2)

>print $ rootParse 1
Struct3_var1 (Struct1 1 2 (StructParam 3 4) 5 6 7 8 (StructParam 9 0))

>print $ rootParse 2
Prelude.undefined

-- but I want something like this
>print $ rootParse 2
Struct3_var2("undefined")
4

2 に答える 2

10

データ型のコンストラクターとして「未実装」を追加し、 の定義で終わるすべての解析にデフォルトのケースを設定するUnimplementedと、ショー インスタンスは自明に機能します。

data Exp = Literal Int
         | Variable String
         | Operator Op Exp Exp
         | Unimplemented

    deriving Show
于 2012-05-25T12:36:02.583 に答える
0

これを達成するかもしれない少し醜いハックは、 undefined によってスローされた例外を検出するために、このクラスの Show インスタンスでunsafePerformIOandを使用することです。catchただし、このアプローチはお勧めしません。

于 2012-05-25T13:41:49.080 に答える