LoginSignup
1
0

More than 5 years have passed since last update.

Re:haskellの数値のなんか

Last updated at Posted at 2014-02-11

haskellの数値のなんかを自分なりに考えてみた。
思いついたやり方は2つ。

Doubleが最も上の階層にあることを利用する方法

IntegerもRationalもDoubleにできるのでこれを利用する。足し算を実行したい型が全てDoubleより下の階層にあることがわかっている場合はこんなんでもよいと思う。

fooDouble :: Foo -> Double
fooDouble (FooInteger x) = fromInteger x
fooDouble (FooDouble x) = x
fooDouble (FooRational x) = fromRat x

fooPlus :: Foo -> Foo -> Double -> Foo
fooPlus (FooDouble _) _ = FooDouble
fooPlus _ (FooDouble _) = FooDouble
fooPlus (FooRational _) _ = FooRational . toRational
fooPlus (FooInteger _) (FooInteger _) = FooInteger . truncate
fooPlus y x = fooPlus x y

addFoo' :: Foo -> Foo -> Foo
addFoo' x y = fooPlus x y $ fooDouble x + fooDouble y

それ以外

特定の型同士を相互変換して足し算を実行する。
この方法だとinstance宣言のときにかなり自由度の高い型のパターンマッチが可能。さらに足し算できない型同士を足そうとしたらコンパイルエラーまで出てくれる。その代わりOverlappingの制限が厳しいので書き下さないといけないケースが多くてつらい。
Type Familyは足し算を実行したあとの結果の型を強制するのに使う。これがないといちいちaddBar x y :: Doubleなどと書かなければいけないのでとてもめんどくさい。

{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, TypeFamilies, UndecidableInstances #-}

data Bar a = Bar a deriving (Show)

class BarLaw a b where
  barPlus :: a -> b -> Result a b

type family Result a b :: *
type instance Result Double a = Double
type instance Result a Double = Double
type instance Result Rational Integer = Rational
type instance Result Rational Rational = Rational
type instance Result Integer Rational = Rational
type instance Result Integer Integer = Integer

instance BarLaw Integer Double where
  barPlus x y = fromIntegral x + y
instance BarLaw Double Integer where
  barPlus x y = x + fromIntegral y
instance BarLaw Rational Integer where
  barPlus x y = x + fromIntegral y
instance BarLaw Integer Rational where
  barPlus x y = fromIntegral x + y
instance BarLaw Rational Double where
  barPlus x y = fromRat x + y
instance BarLaw Double Rational where
  barPlus x y = x + fromRat y
instance (a ~ Result a a, Num a) => BarLaw a a where
  barPlus x y = x + y

addBar :: (BarLaw a b) => Bar a -> Bar b -> Bar (Result a b)
addBar (Bar x) (Bar y) = Bar $ x `barPlus` y

パターンマッチに柔軟性を持たせるか、型に柔軟性を持たせるか、お好きな方で。

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0