Haskellのお勉強 その8
基本的な値と、その周辺の関数
真偽値
Haskellno真偽値はTrueかFalseのみ。その型はBool型。関連関数として、not関数、(&&)関数、(||)関数などがある。
Prelude> not True False Prelude> (&&) True False False Prelude> not True && False False Prelude> False || True True
まあ、基本ですね。
数値
Haskellの整数型には、IntとInteger型がある。Intは範囲の小さな符号付き整数値*1。Integer型は、範囲無制限の整数値を表現することができる。
確認のために、「::」構文を使って型を明示的に宣言してみると以下のようになる。
Prelude> 999999999999999999999999999999999999999 :: Integer 999999999999999999999999999999999999999 Prelude> 999999999999999999999999999999999999999 :: Int -1
整数は、10進法、8進法、16進法の3つのリテラルで表現することができる。
「0o」(ゼロ・オー)を前置すると8進数を表し、「0x」(ゼロ・エックス)を前置すると16進数を表す。
Prelude> 0o644 420 Prelude> 0x1f 31
これもまあ、基本ですね。
Haskellの浮動小数点型には、32ビット表現(単精度)であるFloat型と、
64ビット表現(倍精度)である、Double型がある。
Prelude> 3.14159265358979323 3.1415927 Prelude> 3.14159265358979323 3.141592653589793 Prelude> 1500e+3 1500000.0 Prelude> 1500e-3 1.5
以下で示す他にも、いろいろな数値演算の関数がある。
Prelude> div 33 5 6 Prelude> mod 33 5 3 Prelude> -55 -55 Prelude> negate 55 -55 Prelude> -(55 -50) -5 Prelude> abs $ -50 50 Prelude> floor 3.141592 3 Prelude> ceiling 3.141592 4
Haskellでは、整数型と浮動小数点型の他に、有理数を表現する
Rational型と、複素数を表現するComplex型がある。
Rational型はRatioモジュールを、Complex型はComplexモジュールを
それぞれインポートすると使えるようになる。
有理数: http://www.sampou.org/haskell/report-revised-j/ratio.html
複素数: http://www.sampou.org/haskell/report-revised-j/complex.html
文字と文字列
Haskellの文字はChar型の値。文字コードはUnicodeが使われているが、GHCでは文字自体はUnicodeで表現されているが、
入出力での文字エンコーディングの変換がまだ実装されていない。
Prelude> Char.isUpper 'a' False Prelude> Char.isAlpha 'a' True Prelude> Char.isUpper 'A' True Prelude> Char.isHexDigit 'A' True Prelude> Char.isDigit 'A' False Prelude> Char.chr 97 'a' Prelude> Char.ord 'a' 97 Prelude> map Char.ord "aiueo" [97,105,117,101,111] Prelude> Char.toLower "A" 'a'
以下、主張なエスケープシーケンス
記述例 | 意味 |
---|---|
\t | タブ |
\n | 改行 |
\r | 復帰 |
\v | 垂直タブ |
\f | 改ページ |
\a | ベル |
\b | バックスペース |
\NNN | 10進表記の数値NNNに対応する文字 |
\oNN | 8進表記の数値NNに対応する文字 |
\xNN | 16進表記のNNに対応する文字 |
\^X | コントロールX |
\' | シングルクオート |
\" | ダブルクオート |
\\ | バックスラッシュ |
タプル
Haskellにおけるタプルとは、いくつかの値 (数値型、文字列型など)をひとつにまとめて、あたかもひとつの値のように扱う機能である。
リストや配列が同じ型をまとめるのに対し、タプルは用途や型が異なる型をひとつにまとめるために使われる。
このためタプルの働きは、他言語で言うところの構造体に似ていると言える。
構造体には通常異なる型や名前をもった値がまとめて格納される。
これによって、本来ならばひとつの値しか扱えない箇所 (関数の返り値や、変数への代入、配列の各要素など) で
複数の値を同時に扱うことが可能となる。タプルはこの構造体を匿名にしたようなものと考えても差し支えないだろう。
なお、タプルは基本的に2つの要素以上でなければならず、1つの要素のみのタプルというのはない。
しかし、特別に0要素のタプルはある。0要素のタプルはユニットと呼ばれている。
ユニット(unit)は0要素のタプルである。ソースコード上では「()」と記述され、
また、ユニットの型はリテラルと同じく「()」である。
Prelude> (4,"aiueo") :: (Int,String) (4,"aiueo") Prelude> ("test",45) :: (String,Int) ("test",45) Prelude> (1,"yes",[3,2,1]) :: (Int,String,[Int]) (1,"yes",[3,2,1]) Prelude> ((3,5),"ok",['a','b','c']) :: ((Int,Int),String,[Char]) ((3,5),"ok",['a','b','c']) Prelude> fst ('a',6) 'a' Prelude> snd $ snd ("aiueo",(6,"test")) "test" Prelude> zip [1, 2, 3, 4, 5] [9, 8, 7] [(1,9),(2,8),(3,7)] Prelude> unzip $ zip [1, 2, 3, 4, 5] [9, 8, 7] ([1,2,3],[9,8,7])
リスト
Haskellにおけるリストとは、同じ型の値を並べたもの。Haskellのリストは所謂、一方向リンクリストと同質で、
前方からリストを辿ることは可能だが、後方からリストを辿ることはできない。
Prelude> 1 : 2 : 3 : [] [1,2,3] Prelude> let cons = (:) Prelude> (cons 1 (cons 2 (cons 3 (cons 4 [])))) [1,2,3,4] Prelude> [1..10] [1,2,3,4,5,6,7,8,9,10] Prelude> [2,4..12] [2,4,6,8,10,12] Prelude> null [] True Prelude> null[1,2,3] False Prelude> 1 : 2 : 3 : [4,5] ++ [] [1,2,3,4,5]
リスト内包表記
Haskellにはmap関数やfillter関数を組み合わせた関数を数学的に表現するリスト内包表記(list comprehension)という構文がある。
Prelude> [abs x | x <- [-5..5]] [5,4,3,2,1,0,1,2,3,4,5]
上記のリスト内包表記は、「リスト[-5..5]の各要素に対して(abs x)を集める」と読む。
map関数を使って書くと、 map abs [-5..5]となる。
リスト内包表記を使ったものとして、よくクイックソートを実装した
以下のqsort関数が例としてあげられる。
main = putStr =<< return . unlines . qsort . lines =<< getContents qsort :: (Ord a) => [a] -> [a] qsort [] = [] qsort (x:xs) = qsort lt ++ [x] ++ qsort gteq where lt = [y | y <- xs, y < x] gteq = [y | y <- xs, y >= x]
また、下記の例では、2つのリストの要素の組み合わせが生成される。
Prelude> [(x,y) | x <- ['a','b','c'], y <- [1,2,3]] [('a',1),('a',2),('a',3),('b',1),('b',2),('b',3),('c',1),('c',2),('c',3)]
以下、九九の結果リスト
main = print $ multiplication [1..9] multiplication :: [Int] -> [Int] multiplication zs = [x * y | x <- zs, y <- zs]
*1:具体的な範囲は処理系によって異なる。32ビットマシン上のGHCであれば32ビットの符号付き整数値となる