私はHaskellにかなり慣れていないので、これがばかげた質問ではないことを願っています。私はこのデータ型を持っています:
data N = I Int | D Double deriving (Show, Eq)
(Num a) => (a -> a -> a) -> N -> N -> N
s内の数値に関数を適用N
し、結果とともにNを返すシグネチャを使用して関数を作成しようとしています。N
sが両方ともsの場合は、関数を適用して;D
を返す必要があります。D
一方がanI
で、もう一方がaの場合、 inをaにD
変換し、関数を2つのsに適用して、 ;を返す必要があります。両方がsの場合、関数を適用して。を返す必要があります。これが私がこれまでに持っている(壊れた)コードです:Int
I
Double
Double
D
I
I
widen :: N -> N -> (N, N)
widen (I i) d@(D _) = (D (fromIntegral i), d)
widen d@(D _) i@(I _) = widen i d
widen x y = (x, y)
numOp :: (Num a) => (a -> a -> a) -> N -> N -> N
numOp op x y = case widen x y of (D x', D y') -> D $ x' `op` y'
(I x', I y') -> I $ x' `op` y'
ただし、の両方の行でエラーが発生しnumOp
ます。最初のものは次のとおりです。
Could not deduce (a ~ Double)
from the context (Num a)
bound by the type signature for
numOp :: Num a => (a -> a -> a) -> N -> N -> N
at <line num>
In the second argument of `($)', namely x' `op` y'
In the expression: D $ x' `op` y'
In a case alternative: (D x', D y') -> D $ x' `op` y'
そして2番目:
Couldn't match type `Double' with `Int'
Expected type: Int
Actual type: a
In the second argument of `($), namely x' `op` y'
In the expression: I $ x' `op` y'
In a case alternative: (I x', I y') -> I $ x' `op` y'
両方のエラーの意味を理解していると確信しています。最初の1つは、型シグネチャの情報では、GHCが値コンストラクターに必要なをop
返すと想定するのに十分ではないと言っていると思います。2つ目は、最初の行がそれを意味するので、これは行は、型の値を。のように使用することはできません。しかし、これを行う正しい方法をどこから探し始めるのかわかりません。Double
D
a
Double
a
Int
それが役に立ったら、これを機能させようとしている理由は、Write YourselfaSchemeチュートリアルに沿ってフォローしているからです。チュートリアルのすべての例(特に評価セクション)は整数のみを扱いますが、演習として、整数と浮動小数点数の両方をサポートする機能を追加して、たとえば(+ 1 2.5 2.5)
が戻る6.0
と(+ 1 2 3)
戻るようにします6
。私がこれを間違った方法で考えている場合、またはそれを達成するためのより簡単な方法がある場合は、提案を聞いてみたいです。