Haskellで新しい型を定義する
そもそも、今日はderivingについて書こうと思っていたのですが、その前に型を作る段階で一つ記事が書けるレベルの内容だったので、まずはちょっとした型を定義してみる事にします。
module Main where --型 Bar を作成 newtype Bar = Bar Int deriving (Eq,Read,Show) --Bar と Int 間の変換 fromBar :: Bar -> Int fromBar (Bar a) = a toBar :: Int -> Bar toBar a = Bar a --二項演算の定義を簡易化 calcBar :: (Int -> Int -> Int) -> Bar -> Bar -> Bar calcBar f a b = toBar $ fromBar a `f` fromBar b --Numクラスのインスタンスにする instance Num Bar where x + y = calcBar (+) x y x - y = calcBar (-) x y x * y = calcBar (*) x y abs a = toBar $ abs (fromBar a) signum a = toBar $ signum (fromBar a) fromInteger a = toBar $ fromInteger a --実験用 incBar :: Bar -> Bar incBar x = x + 1
どうでも良い話ですが、あちこちでよく見かけるHaskellのサンプルは、無駄にこ難しい事をやろうとしているなぁと思うことが多々あります。
確かに、上のBar型はInt型の再実装みたいな状態ですけど、新しい型の実装方法について試してみるなら、このくらいシンプルな例でも十分だと思うのですが・・・。
とにかく、上で定義したBar型ですが、普通にInt型と同じように使えます。
*Main> (5::Bar) + 10 Bar 15 *Main> (8::Bar) - 3 Bar 5 *Main> (5::Bar) * 4 Bar 20 *Main> incBar 10 Bar 11
単純にInt型を別名で定義したいのであれば、typeを使えば良いんですけどね。
module Main where type Baz = Int;
*Main> (10::Baz)+5 15 *Main> :t (10::Baz)+5 (10::Baz)+5 :: Baz
ちなみに、除算は Fractional という、また別の型クラスになるみたいです。
Int型にも定義されていないようなので、Bar型で除算できるようにしようと思ったら、もうひと工夫必要でしょう。
*Main> (10::Bar)/2 <interactive>:1:0: No instance for (Fractional Bar) arising from a use of `/' at <interactive>:1:0-10 Possible fix: add an instance declaration for (Fractional Bar) In the expression: (10 :: Bar) / 2 In the definition of `it': it = (10 :: Bar) / 2 *Main> :t (/) (/) :: (Fractional a) => a -> a -> a