2017-01-30 7 views
1

Valueと呼ばれるタイプを作成することですマッチング期待タイプIは現在、やろうとしています何

eval $ Dif (Sum (Num 3) (Num 6)) (Neg 4) 
> 13 

私の現在のコードでは、私は各オペレータをthemselveでテストすることができますそれが機能します。

eval (Dif 3 4) 
>-1 

私は、エラーを取得し、上記のように予想される入力で、ネストされた操作を実行しようとすると問題が発生:

"Couldn't match expected type Int with actual type Value "

私は私の操作を思って、私は問題を理解しようとしていますIntを返さなければならず、私のValueタイプはIntとなるので、次の操作は期待されるタイプでなければなりません。現在の評価関数が実際に何をしているかを調べるためにさまざまな入力をテストしています。

eval (Dif (eval (Sum 3 5)) 4) 
>4 

期待通りの結果が得られます。私はここで間違って何をしていますか?ここで

+0

なぜあなたは 'Int'を取るものに' Value'を入れようとしていますか? 'Num 1 :: Value'ではなく' Sum'が 'Int'を期待しているので、' Sum(Num 1)(Num 2) 'は動作しません。 – AJFarmar

+1

あなたが得た正しい答えは別として、 'Value'を' Num'のインスタンスにすることで、 '1 :: Value'と書くことができます。 – Alec

+1

私は実際にバリュータイプを取っていたことを完全に見落としました。私は間違った考え方のAJFarmer(私は睡眠不足でそれを責めるだろう)にいた。私の投稿は編集されましたが、私はハスケルに新しいので、私は簡単な間違いに苦しんでいます。チップAlecをありがとう! – Sinsarii

答えて

6
data Value = Num Int 
      | Sum Int Int 
      | Dif Int Int 
      | Neg Int 

あなたはValueコンストラクタがInt値でのみ動作することを指定した、例えば、NegはタイプInt -> Valueを持っています。したがってNeg (Neg 1)またはSum (Num 1) (Num 2)のようなものを書くことはできません。ValueのタグなしのIntが必要なタグを使用しようとしているためです。 Lispでは、関数がちょうど1を受け取るときに(Num . 1)を渡したかのようになります。

あなたはValueを受け入れるためにあなたのタイプの定義を変更することができます。

data Value = Num Int 
      | Sum Value Value 
      | Dif Value Value 
      | Neg Value 

さて、これはNumがリテラルIntであるが、他のコンストラクタはValueの上で動作表現を表します。それでeval関数はそれに応じて変更されます:

eval :: Value -> Int 
eval (Num x) = x 
eval (Sum x y) = eval x + eval y 
-- ... 
+1

ありがとう!私はこのセクションをもう一度読んで、自分が何をしたのかを理解しました。あなたの説明は完璧でしたが、ありがとう! – Sinsarii

関連する問題