Haskell入門 第2章から抜粋
リスト型
Prelude> import Data.Char
Prelude Data.Char> map toUpper "abcd"
"ABCD"
Prelude Data.Char> "This is " ++ "book"
"This is book"
Prelude Data.Char> "This is " ++ "book" ++ show [1, 2, 3]
"This is book[1,2,3]"
Prelude Data.Char> "This is " ++ "book" ++ show [1, 2, 3]
"This is book[1,2,3]"
Prelude Data.Char Data.Maybe> filter (\n -> n `mod` 2 == 0) [1..10]
[2,4,6,8,10]
Prelude Data.Char Data.Maybe> foldl (+) 0 [1..10]
55
リストを扱う関数 | 説明 |
---|---|
head | リストを引数にとり、リストの先頭を取得する |
tail | リストを引数にとり、リストの2件目以降を取得する |
map | 関数とリストを引数にとり、リストに関数を適用する |
filter | boolを返す関数とリストを引数にとり、リストからtrueの要素を返す |
foldr | 関数とリストを引数にとり、リストを右結合で集計する |
foldl | 関数とリストを引数にとり、リストを右左結合で集計する |
foldl
:関数 デフォルト値 (head リスト)
foldr
:関数 デフォルト値 (tail リスト)
Prelude> :t map
map :: (a -> b) -> [a] -> [b]
タプル型
Prelude Data.Char> x = (True, [1,2,3]) :: (Bool, [Int])
Prelude Data.Char>
Prelude Data.Char> fst x
True
Prelude Data.Char> snd x
[1,2,3]
Prelude Data.Char> head $ snd x
1
Prelude Data.Char> tail $ snd x
[2,3]
タプルを扱う関数 | 説明 |
---|---|
fst | 1件目の要素を取得する |
snd | 2件目の要素を取得する |
3値以上のタプル型を扱う場合はパターンマッチを使って任意の値をとりだすことができる
# 3値のタプル型を宣言
Prelude Data.Char> x = (4, 5, 6)
# 先頭の値を取得
Prelude Data.Char> let (n,_,_) = x in n
4
# 3番目の値を取得
Prelude Data.Char> let (_,_,n) = x in n
6
Maybe a型
Maybeって何?
値が入ってるかもしれないし、入ってないかもしれない、そんな値を扱いたい時にMaybe型
を使う・・・たぶん。
Maybe
はNothing
とJust
という2つのデータコンストラクターを持っている。
Nothing
は値を持たないデータ型として例外処理などに使える。
Just
は1つの値を持つデータコンストラクタ。
# 徐算関数を定義 ※0除算は例外としてNothing型を返す、それ以外は除算結果をJust型に詰め込む
Prelude Data.Char> :{
Prelude Data.Char| percentage k n | n == 0 = Nothing
Prelude Data.Char| | otherwise = Just (100.0 * k / n)
Prelude Data.Char| :}
# percentage 20 50を表示
Prelude Data.Char> :{
Prelude Data.Char| case percentage 20 50 of Nothing -> "UNKNOWN"
Prelude Data.Char| Just x -> show x
Prelude Data.Char| :}
"40.0"
Prelude Data.Char> import Data.Maybe
Prelude Data.Char Data.Maybe> p = percentage 20 50
Prelude Data.Char Data.Maybe> if isNothing p then "UNKNOWN" else show (fromJust p)
"40.0"
Prelude Data.Char Data.Maybe> p = percentage 20 0
Prelude Data.Char Data.Maybe> if isNothing p then "UNKNOWN" else show (fromJust p)
"UNKNOWN"
Prelude Data.Char Data.Maybe> maybe "UNKNOWN" show (percentage 10 10)
"100.0"
Prelude Data.Char Data.Maybe> maybe "Undefined" show (percentage 10 0)
"Undefined"
Maybe aを扱う関数 | 説明 |
---|---|
isNothing | Maybe aを引数にとり、Nothingか判定する |
fromJust | Maybe aを引数にとり、Just値から値を取得する |
maybe | デフォルト値、関数、Maybe aを引数にとり、関数を初期値で適用しMaybeを返す |
Either a b型
エラーが発生するかもしれない処理を扱いたい時にEither
を使う。
Right型
, Left型
二つのデータコンストラクタを持ち、正常系はRight型
,異常系はLeft型
で扱う。
Prelude Data.Char Data.Maybe> :{
Prelude Data.Char Data.Maybe| percentage k n | n == 0 = Left "Illegal division by zelo"
Prelude Data.Char Data.Maybe| | otherwise = Right (100.0 * k / n) :: Either String Double
Prelude Data.Char Data.Maybe| :}
Prelude Data.Char Data.Maybe>
Prelude Data.Char Data.Maybe> -- show
Prelude Data.Char Data.Maybe> :{
Prelude Data.Char Data.Maybe| case percentage 20 50 of Left err -> err
Prelude Data.Char Data.Maybe| Right x -> show x
Prelude Data.Char Data.Maybe| :}
"40.0"
Prelude Data.Char Data.Maybe> -- 実行
Prelude Data.Char Data.Maybe> import Data.Either
Prelude Data.Char Data.Maybe Data.Either> either id show (percentage 10 10)
"100.0"
Prelude Data.Char Data.Maybe Data.Either> either id show (percentage 10 0)
"Illegal division by zelo"
再帰処理の例
Prelude> :{
Prelude| -- n <= 1 の時はnを返す
Prelude| fact n | n <= 1 = 1
Prelude| | otherwise = n * fact (n - 1)
Prelude| :}
Prelude>
Prelude> fact 10
3628800
モジュール
記法:module モジュール名(公開する識別子) where
記法:module モジュール名 where -- 識別子を指定しなかった場合は全てが公開される
module Main(main) where
-- mainモジュールの処理
main :: IO () -- ()<Unit型>はJavaのvoidみたいなもの
main = ...
モジュールの利用
REPL: :module モジュール名
Haskellファイル: import モジュール名(識別子) -- 識別子を未指定の場合はすべて
モジュールを読み込むことでモジュールが公開している識別子を利用できる
Prelude Data.Char Data.Maybe Data.Either> :module Data.Char
Prelude Data.Char>
Prelude> -- モジュール読み込み削除
Prelude Data.Char> :module -Data.Char
Prelude>
Prelude> -- モジュール読み込み追加
Prelude> :module +Data.Char
Prelude Data.Char> -- <--現在読み込んでいるモジュールが表示されている
Prelude>
Prelude> -- 読み込んでるモジュール情報を取得
Prelude Data.Char> :show imports
import Data.Char
import Prelude -- implicit
- mainプログラムからモジュールを利用する
module Example.HelloSample(helloSample, byeSample) where
helloSample :: String -> IO ()
helloSample name = putStrLn(getHello name)
byeSample :: String -> IO ()
byeSample name = putStrLn(getBye name)
getHello :: String -> String
getHello name = "hello, " ++ name ++ "!!"
getBye :: String -> String
getBye name = "good bye, " ++ name ++ "!!"
-- Mainモジュール
module Main(main) where
import Example.HelloSample
main :: IO ()
main = do -- do構文を使うことでIO ()を逐次実行してくれる
helloSample "Haskell"
byeSample "Haskell"
$>stack runghc myapp.hs
hello, Haskell!!
good bye, Haskell!!
パッケージ
モジュールを再利用、再配布できる単位でまとめたもの。
パッケージの構成はCabalの形式に則って作成する。
パッケージはHackage上で公開、共有されている。
StackageはHackage上のパッケージから選別し管理している。
Stackageは依存関係の解決を簡潔にし、問題なくビルドできるものが利用できるので、Stackageを利用するのがおすすめ。
Hoogleはモジュールの識別子の検索することができる。