単なる読書メモ
代数的データ型
定義の仕方1 - 構造体っぽい
ラベルなしコンストラクター
-- Student型の定義 data Student = Student String String -- インスタンス化 student = Student "Paul" "Smith" -- パターンマッチ printStudent:: Student -> IO() printStudent (Student fn ln) = print (fn ++ " " ++ ln)
ラベルありコンストラクター
-- Student型の定義 data Student = Student { fstName:: String, lstName:: String } -- インスタンス化 student = Student {fstName = "Paul", lstName = "Smith"} -- パターンマッチ printStudent:: Student -> IO() printStudent Student{fstName = fn, lstName = ln} = putStrLn (fn ++ " " ++ ln) -- fstNameだけを取り出す関数fstNameが自動で生成される printFirstName:: Student -> IO() printFirstName = putStrLn $ fstName -- 値を更新した新しいStudentオブジェクトの生成 replaceFirstName:: Student -> String -> Student replaceFirstName student fn = student {fstName = fn}
多層的な型
data Stack = Stack[a]
定義の仕方2 - enum
-- 色型の定義 data Color = Black | White | Green | Red | Blue | Purple | Yellow | Orange | Cyan
定義の仕方 - 共用体っぽい
-- スタックの定義 data Stack a = Empty | Push a (Stack a) -- スタックに対する操作の定義 (|>) :: a -> Stack a -> Stack a x |> stk = Push x (stk) infixr 5 |> isEmptyStack:: Stack a -> Bool isEmptyStack Empty = True isEmptyStack _ = False popStack:: Stack a -> (a, Stack a) popStack (Push x stk) = (x, stk)
型の別名
-- StringにFilePathという別名を付与する type FilePath = String
型クラス
定義の仕方
class Matrix a where (***):: a -> a -> Float
クラスの継承
型クラスOrd a
は型クラスEq a
を継承しているので次のような定義になっている
class (Eq a) => Ord a where compare:: a -> a -> Ordering (<), (<=), (>), (>=):: a -> a -> Bool max, min:: a -> a -> a
インスタンス宣言
型を型クラスのインスタンスであると宣言する方法
-- 型クラスAppendの定義 class (Eq a) => Matrix a where (***):: a -> a -> Float -- スタック型の定義 data Vector = Vec Float Float -- インスタンス宣言 instance Matrix Vector where (Vec x y) *** (Vec a b) = x * a + y * b instance Eq Vector where (Vec x y) == (Vec a b) = (x == a) && (y == b)
HaskellはHaskellでこれまでのJava言語圏で生きてきた僕にはなかなかつらいところがあったりする。特にコンパイル時の型推論によるコンパイルエラーなど。まあ、でも意地になってググったりしてやってて、それはそれで楽しい。