LoginSignup
2
1

More than 3 years have passed since last update.

Haskell入門から学ぶ

Last updated at Posted at 2020-02-09

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型を使う・・・たぶん。
MaybeNothingJustという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 -- 識別子を指定しなかった場合は全てが公開される

Main.hs
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プログラムからモジュールを利用する
Example/HelloSample.hs
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 ++ "!!"
myapp.hs
-- 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はモジュールの識別子の検索することができる。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1