タイプ#
特徴#
強力なタイプ
静的な
自動的に推論されることができる
基本タイプ#
Char
Bool
Int 一般的に使用される 固定幅の整数 通常32/64ビット幅
Integer あまり使用されない 可変長
Double 一般的に使用される 浮動小数点数
Float あまり使用されない 計算が遅い
Prelude> :type 'a'
'a' :: Char
Prelude> 'a' -- 自動的に推論される
'a'
::記号
Prelude> 'a' :: Char -- 明示的な署名
'a'
関数の呼び出し#
Prelude> odd 3
True
Prelude> compare 2 3
LT
例:LT EQ GT
Prelude> (compare 2 3) == LT
True
Prelude> compare (sqrt 3) (sqrt 6) -- ここで括弧を取り除くことはできません
LT
複合データ型:リストとタプル#
違い?#
リストは任意の長さであり、同じタイプの値のみを含むことができます。
タプルの長さは固定されていますが、異なるタイプの値を含むことができます。
再帰可能性#
[[Int]]
は [Int] タイプの値を含むリストであり、 [Int]
は Int タイプの値を含むリストであり、a の型変数を Int タイプで置き換えます。
リスト [] と head、tail、last;take、drop#
head は最初の要素を取得し、tail は最初以外のすべてを取得します。
last は最後の要素を取得します。
Prelude> head [1, 2, 3, 4]
1
Prelude> head []
*** Exception: Prelude.head: empty list
Prelude> tail "list"
"ist"
ghci> last [1,2,3]
3
Prelude> take 2 [1, 2, 3, 4, 5]
[1,2]
Prelude> drop 2 [1, 2, 3, 4, 5]
[3,4,5]
Prelude> drop 4 [1, 2]
[]
Prelude> drop (-1) "foo" --最初の引数が0以下の場合、drop関数は入力リスト全体を返します
"foo"
タプル () と fst、snd#
サイズは少なくとも 2 です
タプルの型は、含まれる要素の数、位置、および型によって決まります
Prelude> :type (True, "hello")
(True, "hello") :: (Bool, [Char])
Prelude> (4, ['a', 'm'], (16, True))
(4,"am",(16,True))
Prelude> :t ()
() :: ()
Prelude> fst (1, 'a')
1
Prelude> snd (1, 'a')
'a'
タプルの使用例#
-
関数が複数の値を返す必要がある場合、これらの値をタプルにまとめて、関数の値としてタプルを返すことができます。
-
固定長のコンテナを使用する必要がありますが、カスタムタイプを使用する必要がない場合、値をタプルでラップすることができます。
式を関数に渡すために括弧を使用する#
a b c d は (((a b) c) d) と等しい
純粋性#
副作用のある関数は 不純(impure)関数 と呼ばれ、副作用のない関数は 純(pure)関数 と呼ばれます。
副作用とは、関数内のグローバル変数の変更可能性、つまり、ある時点の値に依存することです。本質的には、関数の見えない(invisible)入力または出力です。Haskell の関数はデフォルトで副作用がありません:関数の結果は、明示的に渡されたパラメータにのみ依存します。
不純な関数の型シグネチャはすべて IO で始まります。以下は検出例です:
Prelude> :type readFile
readFile :: FilePath -> IO String
-- 不純な関数の型シグネチャはすべて IO で始まります
.hs ファイルのロード#
ghci で :load
を使用します
変数#
変数が式にバインドされると、その変数の値は変更されません。.hs ファイルではできませんが、ghci コマンドラインでは可能です。
例:[Assign.hs]
条件付き評価#
異なるブランチ間の型は同じでなければなりません。
例:
[myDrop.hs]
-- file: ch02/myDrop.hs
myDrop :: Int -> [a] -> [a]
myDrop n xs = if n <= 0 || null xs -- ## nullの使用法
then xs -- インデントは省略できません
else myDrop (n - 1) (tail xs) -- インデントは省略できません
-- 代入(substitution)と書き換え(rewriting)
-- 変数nとxsを代入しました
-- myDrop関数を書き換えました
-- ## 遅延評価
-- 1行にまとめることもできます 例:[myDropX.hs](ch02/myDrop.hs)
-- ## 条件付き評価
-- null xsはxs == nullではありません
-- thenとelseの後の式は「ブランチ」と呼ばれます。
-- 異なるブランチ間の型は同じでなければなりません。
-- ifはブランチではありません。
-- 例:
-- Prelude> if True then 1 else "foo"
-- <interactive>:2:14:
-- No instance for (Num [Char])
-- arising from the literal `1'
-- Possible fix: add an instance declaration for (Num [Char])
-- In the expression: 1
-- In the expression: if True then 1 else "foo"
-- In an equation for `it': it = if True then 1 else "foo"
->
1 行に簡略化できます [myDropX.hs]
-- file: ch02/myDropX.hs
myDropX n xs = if n <= 0 || null xs then xs else myDropX (n - 1) (tail xs)
遅延評価#
例:[isOdd.hs]
-- file: ch02/isOdd.hs
isOdd n = mod n 2 == 1
-- ghci> isOdd (1+2)
-- True
--一般的には:XXXXXX
-- 最初:(1+2)
-- 2番目:mod 3 2
-- 3番目:1 == 1
-- True
--しかし、Haskellでは:
--(1+2)は最後に計算されます!実際に必要なときにisOdd (1 + 2)の値を計算します
--未評価の式の追跡レコードは「チャンク」と呼ばれます
再帰#
遅延評価に注意し、再帰 -> 再帰の終了 -> 再帰の戻り値
解説
例:[myDrop.hs]
多相性#
パラメータ多相性#
Prelude> :type last
last :: [a] -> a
ghci> last [1,2,3]
3
last に [Char] タイプのリストを渡すと、コンパイラはすべての a を Char で置き換え、[Char] -> Char のタイプを持つ last 関数を得ます。同様に、Int などの任意のタイプでも可能です。このようなタイプの多相性はパラメータ多相性と呼ばれます。
パラメータ多相性は、入力パラメータの実際のタイプを知る方法はありません。
不足#
Haskell にはサブクラス多相性や強制多相性(coercion polymorphism)はありません。
多パラメータ関数のタイプ#
例:
Prelude> :type take
take :: Int -> [a] -> [a]