haskellの数値のなんかのコードを自分なりに書きなおしてみた。
型クラスはあまり使いこなせないので、変換関数を作ってかます方針で。 型変換の条件はわかりやすくなったと思う。
module Main where
import Data.Ratio
import Numeric
data Foo = FooInteger Integer
| FooRational Rational
| FooDouble Double
deriving (Show)
addFoo :: Foo -> Foo -> Foo
addFoo (FooInteger x) (FooInteger y) =
FooInteger $ x + y
addFoo (FooInteger x) (FooRational y) =
FooRational $ fromInteger x + y
addFoo (FooRational x) (FooInteger y) =
FooRational $ x + fromInteger y
addFoo (FooRational x) (FooRational y) =
FooRational $ x + y
addFoo (FooInteger x) (FooDouble y) =
FooDouble $ fromInteger x + y
addFoo (FooDouble x) (FooInteger y) =
FooDouble $ x + fromInteger y
addFoo (FooRational x) (FooDouble y) =
FooDouble $ fromRat x + y
addFoo (FooDouble x) (FooRational y) =
FooDouble $ x + fromRat y
addFoo (FooDouble x) (FooDouble y) =
FooDouble $ x + y
-- 以下新規コード
toD :: Foo -> Double
toD (FooInteger v) = fromInteger v
toD (FooRational v) = fromRat v
toD (FooDouble v) = v
toR :: Foo -> Rational
toR (FooInteger v) = fromInteger v
toR (FooRational v) = v
addFoo' :: Foo -> Foo -> Foo
addFoo' x@(FooDouble _) y = FooDouble $ toD x + toD y
addFoo' x y@(FooDouble _) = FooDouble $ toD x + toD y
addFoo' x@(FooRational _) y = FooRational $ toR x + toR y
addFoo' x y@(FooRational _) = FooRational $ toR x + toR y
addFoo' (FooInteger x) (FooInteger y) = FooInteger $ x + y
main :: IO ()
main = do
let x = FooInteger 3
let y = FooRational (3%4)
let z = FooDouble 2.0
print "original version"
print $ addFoo x x
print $ addFoo x y
print $ addFoo x z
print $ addFoo y y
print $ addFoo y z
print $ addFoo z z
print "my version"
print $ addFoo' x x
print $ addFoo' x y
print $ addFoo' x z
print $ addFoo' y y
print $ addFoo' y z
print $ addFoo' z z