1

任意の場所に要素( "$"、Undefined)が含まれている可能性のあるペアのリストを検索しようとしていました。その特別な要素の前にあるリストの部分だけを検索したかったので、次のようなものを試しました(すでに要素nとリストxsを引数として取ることが意図されています):

checkNotSameScope :: Env -> VarName -> Expr -> Expr
checkNotSameScope (xs:("$", Undefined):_) n e = if alreadyThere n xs then BoolLit False
                                                   else BoolLit True

しかし、それは機能しません。コンパイラは、(xs:..)が私のリストの前にあるSINGLE値のみを処理することを示しているようです。リストの最初のチャンクを示すために:を使用することはできません。単一の要素のみ。振り返ってみると、これは理にかなっています。そうでなければ、コンパイラはどうやって何をすべきかを知るのでしょうか?「x」のようなものに「s」を追加しても、魔法のように複数の要素が作成されることはありません。しかし、どうすればこれを回避できますか?

4

3 に答える 3

5

残念ながら、スマートコンパイラや言語を使用しても、一部のプログラミングは避けられません...

あなたの場合、特定の要素までのリストの一部が必要なようです。より一般的には、ある条件までのリストを見つけるために、標準ライブラリtakeWhile関数を使用できます。次に、それを実行できますalreadyThere

checkNotSameScope :: Env -> VarName -> Expr -> Expr
checkNotSameScope xs n e = if alreadyThere n (takeWhile (/= ("$", Undefined)) xs)
                           then BoolLit False
                           else BoolLit True

("$", Undefined)発生しないリストに必要なものではない可能性があるため、注意してください。

于 2012-10-14T17:34:13.677 に答える
2

Joachimの答えと同様に、を使用できます。これにより、発生しない場合breakを検出できます(これが必要な場合)。("$", Undefined)すなわち

checkNotSameScope xs n e = case break (== ("$", Undefined)) xs of
                             (_, [])  -> .. -- ("$", Undefined) didn't occur!
                             (xs', _) -> BoolLit . not $ alreadyThere n xs'

("$", Undefined)(注:最初のケースをチェックするには、リストを最後までトラバースする必要があるため、このソリューションではある程度の怠惰が失われます。)

于 2012-10-14T17:52:03.863 に答える
1

Haskellは、この種のパターンマッチングをそのままでは実行できませんが、たとえばCLIPSやF#など、アクティブなパターンを使用して実行できる言語もあります。

ただし、Haskellの既存のパターンマッチング機能を使用して、同様の結果を得ることができます。まず、次のように定義されたdeconstructという関数を定義しましょう。

deconstruct :: [a] -> [([a], a, [a])]
deconstruct [] = []
deconstruct [x] = [([], x, [])]
deconstruct (x:xs) = ([], x, xs) : [(x:ys1, y, ys2) | (ys1, y, ys2) <- deconstruct xs]

この関数が行うことは、リストxsのすべての分解を次の(ys1, y, ys2)ような形式のトリプルに取得することys1 ++ [y] ++ ys2 == xsです。したがって、たとえば:

deconstruct [1..4] => [([],1,[2,3,4]),([1],2,[3,4]),([1,2],3,[4]),([1,2,3],4,[])]

これを使用して、関数を次のように定義できます。

checkNotSameScope xs n e =
    case [ys | (ys, ("$", Undefined), _) <- deconstruct xs] of
        [ys] -> BoolLit $ not $ alreadyThere n xs
        _    -> -- handle the case when ("$", Undefined) doesn't occur at all or more than once

do-notationを使用して、探しているものにさらに近いものを取得できます。

checkNotSameScope xs n e = BoolLit $ not $ any (alreadyThere n) prefixes
    where
        prefixes = do
            (xs, ("$", Undefined), _) <- deconstruct xs
            return xs

ここで起こっていることがいくつかあります。まず、prefixes変数は、ペアの前にあるすべてのプレフィックスリストを格納します。("$", Undefined)ペアが入力リストにない場合は、何も格納しませんxs。次に、any関数を使用してalreadyThere n、プレフィックスのいずれかに対してTrueが得られるかどうかを確認します。そして残りは、関数のロジックを完成させることです。

于 2012-10-15T19:46:49.433 に答える