私はタイプを持っています
data Value = Int Integer
| Float Double
| Complex (Complex Double)
| ... (other, non-numeric types)
関連するエラータイプ
data ValueError = TypeMismatch Value | ... (other constructors)
type ThrowsError = Either ValueError
階層内の最上位の型への自動強制と、オペランドの1つが数値型でない場合のエラーシグナリング、つまり関数を使用して、型に対してジェネリック二項演算を実装したいと思います。
binaryOp :: Num a => (a -> a -> a) -> Value -> Value -> ThrowsError Value
たとえば、私が書くことができるように
(binaryOp (+)) (Int 1) (Int 1) ==> Right (Int 2)
(binaryOp (+)) (Int 1) (Float 1.0) ==> Right (Float 2.0)
(binaryOp (+)) (Int 1) (String "1") ==> Left (TypeMismatch (String "1"))
これを行う簡単な方法はありますか?私の最初の考えは、次のようなものを定義することでした
data NumType = IntType | FloatType | ComplexType
機能と一緒に
typeOf :: Value -> NumType
typeOf (Int _) = IntType
...
promote :: Value -> Value
promote (Int n) = Float (fromInteger n)
promote (Float n) = Complex (n :+ 0)
しかし、私はそれを機能させるのに苦労しています。何かアドバイス?
もう少しコンテキスト。私はSchemeインタープリターを書いていますが、Scheme数値タワーを実装したいと思います。
実際、私は説明したものよりも少し複雑なことを達成したいと思っています。なぜなら、次の行に沿って、任意の数の引数に適用できるものが必要だからです。
binaryOp :: Num a => (a -> a -> a) -> [Value] -> ThrowsError Value
これはで実装されますがfoldl1
、もっと単純な問題を解決できれば、このもっと複雑な問題も解決できると思います。