2

私は学生で、プログラミング コースでは Haskell を学ぶ必要があります。だから私はそれが初めてで、それほど多くの経験がありません。また、フォーラムに質問を投稿することに慣れていません。

そのため、まずライブラリを投稿します。一緒に作業する必要があります。(DA : 決定論的オートマトン)

type State = Integer
type DA = (State, State -> Char -> State, State -> Bool)
type ListDA = (State, [((State, Char), State)], [State])

a :: DA
a = (0, delta, (==1))
  where
    delta 0 'a' = 1
    delta 1 'a' = 1
    delta 2 'a' = 1
    delta 0 'b' = 2
    delta 1 'b' = 2
    delta 2 'b' = 2

toDA :: ListDA -> DA
toDA (start, delta, final) = (start, deltaFun delta, (`elem` final))
  where deltaFun dl = curry (fromMaybe 0 . flip lookup dl)  

toDA 関数は、リスト表現でオートマトンを取得し、それをオートマトンに変換します。この機能とライブラリの残りの部分は、講義の議長によって与えられます。

問題は、型の関数を書くことです

advance :: DA -> State -> String -> State

この関数は、オートマトン、状態、および文字列を受け取り、文字列を読み取った後にオートマトンの状態を返します。

これまでのところ、アイデアは明確です。タイプ DA のオートマトンは、状態遷移関数デルタを持っています。したがって、関数「advance」は、何らかの方法でそのデルタ関数を呼び出す必要があります。しかし、型に統合された関数にアクセスするにはどうすればよいでしょうか?

4

2 に答える 2

4

そのためにパターンマッチングを使用します:

advance :: DA -> State -> String -> State
advance (start, step, accept) fromState chars = ....

typeキーワードは型の同義語を導入するだけです。DAはトリプルの同義語です(Integer, Integer -> Char -> Integer, Integer -> Bool)

あなたのネーミングは紛らわしいです。deltaautomatonの定義でaは状態遷移関数ですが、toDAfunction の定義では、という名前のパラメーターdeltaはリストです。ListDAtype は、トリプル (別のもの - 状態、遷移のリスト、および許容可能な状態のリスト) の単なるシノニムでもあります。

ループの再帰を使用して、これをコーディングする方法を次に示します。

advance (_, step, _) fromState chars = go fromState chars
  where
    go s []     = ...  -- stop, and produce the state as the answer,
                       -- when the input string (list of chars) has ended
    go s (c:cs) =         -- if not, then
      let s2 = step s c   -- make one step
      in  go .......      -- and loop with new values

startここではor変数は必要ないacceptので、無名変数パターンを使用できることに注意して_ください。また、stepは type の関数でありState -> Char -> State、そこでの関数呼び出しで使用される引数の順序を決定します。つまり、状態と文字を受け取り、新しい状態を生成します。

Haskell をまったく知らない場合は、こちらのような優れたチュートリアルを読む (そして作業する) と役立つでしょう。

最後に、「フォーラムに質問を投稿することに慣れていない」とおっしゃいましたので、回答の受け付けと一般的なFAQをお読みください。

于 2012-11-20T11:55:07.957 に答える
3

関数は実際には Haskell の他のタイプのデータと何の違いもありません。評価するまでは、グローバルに定義された関数、パターン マッチングによって取得された関数変数、名前のないラムダの間に違いはありません。

この場合、Will Ness が言ったように、名前のパターン マッチングによって関数を取得するのが最も簡単です。

advance (start, delta, terminate) = result

次に、このスコープで、他の関数deltaと同様に使用できます。terminate

 where result = delta start 'b'  -- or whatever, conditional on terminate...
于 2012-11-20T12:04:38.670 に答える