2016-11-28 3 views
1

私は以下のハスケルコードを持っています。問題は最初の2人の警備員のために文節(enigmaInput,_) = (filter (\(a,b) -> b == cipherChar0) stecker)!!0が失敗することです。最後の2人のガードだけにどのように割り当てることができますか?ありがとう!特定のガードのwhere節

followMenu :: Crib->Menu->Stecker->Offsets->Maybe Stecker 
followMenu c [] s o = Just s 
followMenu crib menu stecker offsets 
    | (length stecker) == 1 && initAdd == Nothing = Nothing 
    | (length stecker) == 1 && initAdd /= Nothing = followMenu crib (tail menu) (fromMb initAdd) offsets 
    | (length stecker) /= 1 && normalAdd == Nothing = Nothing 
    | otherwise = followMenu crib (tail menu) (fromMb normalAdd) offsets 
    where (_,_,cipherChar0) = crib!!(menu!!0) 
     (_,_,cipherChar1) = crib!!(menu!!1) 
     (enigmaInput,_) = (filter (\(a,b) -> b == cipherChar0) stecker)!!0 
     enigmaOutput = enigmaEncode enigmaInput (SimpleEnigma rotor3 rotor2 rotor1 reflector1) offsets 
     (_,initInput) = stecker!!0 
     initOutput = enigmaEncode initInput (SimpleEnigma rotor3 rotor2 rotor1 reflector1) offsets 
     (_,_,initCipher) = crib!!(menu!!0) 
     initAdd = steckerAdd initOutput initCipher stecker 
     normalAdd = steckerAdd enigmaOutput cipherChar1 stecker 
+2

コードを単純化する大きなチャンスがありません。 'initAdd'と' normalAdd'の値を明示的にチェックする必要はありません。 'fm = \ add - followMenu crib(tail menu)add offsets'を定義し、' stecker'の長さに応じて 'fmap fm initAdd'と' fmap fm normalAdd'を呼び出してください。 – chepner

+1

また、長さとインデックスをチェックするのではなく、 'stecker'でパターンマッチングをすると、物事もきれいになります。私はあなたの質問にも対処すると思います。 – luqui

答えて

1

enigmaInputの値が必要になるまで(filter (\(a,b) -> b == cipherChar0) stecker)!!0が評価されることはありませんので、あなたは本当に、する必要はありません、あなたは最初の2つのガードのケースでenigmaInputを使用しないでください。これは、遅延評価の優れた機能です。

where句をガード付きの方程式の一部に含めることはできませんが、パターンマッチやガードの再構成だけではありません。

+1

私は2要素 'stecker'を試してみるとうまくいきますが、1要素' stecker'を試してみると、このエラーがあります。***例外:Prelude !! !!:インデックスが大きすぎます。 !! 0'は1要素 'stecker'の空リストを返します –

+1

最初のいずれかで' enigmaInput'を使わないとうまくいかない場合は、フィルタ(\(a、b) - > b == cipherChar0)stecker) 2件。あなたのプログラムでは、他にもたくさんの '!! 'が使われています。 –