「Haskell入門ハンズオン!」事前資料 - 3/3

# やってみよう

## 「Haskell入門ハンズオン!」事前資料の一覧

1. [概要](http://qiita.com/YoshikuniJujo/items/11d532719bc64f883386)
2. [処理系の導入と対話環境](http://qiita.com/YoshikuniJujo/items/088a7caea9bd3fe59e3a)
3. やってみよう

## ファイルに保存した定義を読みこむ

ファイルに保存した定義を、対話環境に読みこんでみる。まずは、好きなエディタ(例ではVim)で、ファイルを作成する。

```
% vim fruits.hs
myFavoriteFruit = "apple"
```

これを、対話環境に読みこむ。

```haskell
% stack ghci
Prelude> :load fruits.hs
*Main>
```

値を表示してみよう。

```haskell
*Main> myFavoriteFruit
"apple"
```

対話環境はそのままにして、別のターミナルでファイルを編集する。

```
% vim fruits.hs
myFavoriteFruit = "banana"
```

対話環境で値を表示する。ファイルを再読み込みするためには、コマンド:reloadを使う。

```haskell
*Main> :reload
*Main> myFavoriteFruit
"banana"
```

## 関数を定義する

関数doubleを定義してみる。

```haskell
% vim functions.hs
double x = x * 2
```

## 関数を使う

関数doubleを使ってみる。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> double 8
16
```

## 関数リテラル

関数リテラルを使うと、関数に名前をつけずに直接、作ることができる。関数定義は、関数リテラルによって作った関数で、変数を束縛していると考えることができる。

```haskell
*Main> (\x -> x * 2) 8
16
```

## 演算子と関数

演算子と関数とには、見た目のちがいだけしかない。演算子には、記号列を使う。また、中置記法となる。演算子と関数とは、``や()でたがいに変換できる。

```hs
*Main> 3 + 5
8
*Main> (+) 3 5
8
*Main> div 128 5
25
*Main> 128 `div` 5
25
```

## 型を宣言する

変数luckyを定義する。Integer型として宣言することにしよう。

```haskell
% vim functions.hs
lucky :: Integer
lucky = 7
```

関数doubleにも型宣言をつけてみよう。

```haskell
double :: Integer -> Integer
double x = x * 2
```

対話環境に読みこもう。

```haskell
*Main> :reload
*Main> lucky
7
*Main> :type lucky
lucky :: Integer
*Main> double lucky
14
```

## 数値型の例

数値をあらわす型には、数値の種類に応じて、さまざまなものがある。たとえば、整数値をあらわす型Integerや、浮動小数点数をあらわす型Doubleなどがある。

## 型注釈

Haskellには、さまざまな型の値に解釈されることのある、多相的な式を書くことができる。このような式では、型注釈をつけないと、ひとつの型の値として評価できないことがある。たとえば、数値リテラルなども、そのような式のひとつである。対話環境で試してみよう。

```haskell
*Main> 123 :: Integer
123
*Main> 123 :: Double
123.0
```

## Bool値

Bool値とは、偽(そうでない)と真(そうである)とをあらわす、ふたつの値のこと。

```haskell
*Main> False
False
*Main> True
True
```

## Maybe値

Maybe値とは、値がないかもしれない値。「失敗するかもしれない」関数の返り値として使われる。値があるときは「Just 値」のように表記/表示され、値がないときには「Nothing」のように表記/表示される。

```haskell
*Main> Just 8
Just 8
*Main> Nothing
Nothing
```

## タプル

タプルについても、試してみよう。たとえば、つぎのようなタプルを定義する。

```haskell
% vim functions.hs
taro :: (String, Integer)
taro = ("Taro Yamada", 35)
```

対話環境で、みてみよう。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> taro
("Taro Yamada",35)
*Main> :type taro
(String,Integer)
```

## パターンマッチ

パターンマッチは、Haskellでは本質的な機能のひとつ。分岐と、複合的な値からの値のとりだしとが、パターンマッチによって実現される。たとえば、失敗するかもしれない計算の結果を受けとって、値をかえす関数を、みてみよう。

```haskell
% vim functions.hs
helloTo :: Maybe String -> String
helloTo (Just n) = "Hello, " ++ n ++ "!"
helloTo Nothing = "Hello, customer!"
```

タプルの、それぞれの要素の取り出しも、パターンマッチでできる。

```haskell
human :: (String, Integer) -> String
human (n, a) = n ++ "(" ++ show a ++ ")"
```

関数showは数値を文字列に変換している。リテラルもパターンとして使える。

```haskell
safeRecip :: Double -> Maybe Double
safeRecip 0 = Nothing
safeRecip x = Just (1 / x)
```

それぞれの関数を試してみよう。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> helloTo (Just "Yoshikuni")
"Hello, Yoshikuni!"
*Main> helloTo Nothing
"Hello, customer!"
*Main> human ("Taro Yamada", 32)
"Taro Yamada(32)"
*Main> safeRecip 8
Just 0.125
*Main> safeRecip 0
Nothing
```

### ワイルドカード

値に束縛された変数を使わないときには、ワイルドカードが使える。ワイルドカードはアンダーバーで示される。

```haskell
% vim functions.hs
isNothing Nothing = True
isNothing (Just _) = False
```

試してみよう。

```haskell
*Main> :reload
*Main> isNothing Nothing
True
*Main> isNothing (Just 8)
False
```

### @パターン

@パターンを使うと、変数束縛したうえで、さらに細かいパターンにマッチさせることができる。

```haskell
% vim functions.hs
atPattern :: Maybe Integer -> String
atPattern jx@(Just x) = show jx ++ ": " ++ show x
atPattern Nothing = ""
```

試してみよう。

```haskell
*Main> :reload
*Main> atPattern (Just 8)
"Just 8: 8"
*Main> atPattern Nothing
""
```

### ガード構文

Bool値に対するパターンマッチは頻出なので、特別な構文がある。安全に平方根をもとめる関数を定義してみる。

```haskell
% vim functions.hs
safeSqrt :: Double -> Maybe Double
safeSqrt x
        | x < 0 = Nothing
        | otherwise = Just (sqrt x)
```

試してみよう。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> safeSqrt 9
Just 3.0
*Main> safeSqrt 2
Just 1.142135623730951
*Main> safeSqrt (- 5)
Nothing
```

### if式

おなじことをif式で書いてみる。

```haskell
% vim functions.hs
safeSqrt' :: Double -> Double
safeSqrt' x = if x < 0 then Nothing else Just (sqrt x)
```

うえとおなじようにして、試してみよう。

## case式

case式を使うと、関数定義ではなく式のなかでパターンマッチができる。

```hs
% vim functions.hs
yesNo :: Char -> Maybe Bool
yesNo c = case c of
        'n' -> Just False
        'y' -> Just True
        _ -> Nothing
```

試してみよう。

```hs
*Main> :reload
*Main> yesNo 'y'
Just True
*Main> yesNo 'c'
Nothing
```

## 多相

多相性のある関数を定義してみよう。ふたつめの引数を無視する関数は、つぎのようになる。

```haskell
% vim functions.hs
ignoreSecond :: a -> b -> a
ignoreSecond x y = x
```

第1引数、第2引数ともに、どのような型であっても、この関数は実行できる。また、第1引数と返り値の型は、おなじでなければならないので、おなじ型変数aで表現されている。試してみよう。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> ignoreSecond 8 "hello"
8
*Main> ignoreSecond False 123.45
False
*Main> :type ignoreSecond
ignoreSecond :: a -> b -> a
```

## 型シノニム

予約語typeによる構文を使って、型の別名を定義することができる。

```haskell
% vim functions.hs
type Human = (String, Integer)

showHuman :: Human -> String
showHuman (n, a) = n ++ "(" ++ show a ++ ")"
```

試してみよう。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> showHuman ("Taro", 39)
"Taro(39)"
```

### 型引数

型シノニムの定義には、型引数を使うことができる。

```haskell
% vim functions.hs
type Check a = (Bool, a)

tasks :: [Chack String]
tasks = [(False, "Shopping"), (True, "Walking")]
```

対話環境で見てみる。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> tasks
[(False,"Shopping"),(True,"Walking")]
*Main> :type tasks
tasks :: [Check String]
```

## モジュールの導入

ソースファイルのなかでモジュールを導入するには、予約語importを使う。

```haskell
% vim useMaybe.hs
import Data.Maybe (fromMaybe)

maybe0 :: Maybe Integer -> Integer
maybe0 = fromMaybe 0
```

試してみよう。

```hs
% stack ghci
Prelude> :load useMaybe.hs
*Main> maybe0 (Just 8)
8
*Main> maybe0 Nothing
0
```

## コメント

--から行末までと、{-と-}とで、かこまれた部分とは、コメントとなる。コメントはコードに影響をあためない。

```haskell
% vim functions.hs
some :: Integer
some = 8        -- some is 8

hoge :: Integer -> Integer
hoge x = x * 3
{-
hoge 3 = 9
hoge 10 = 30
...
-}
```

試してみよう。

```haskell
% stack ghci
Prelude> :load functions.hs
*Main> some
8
*Main> hoge 5
15
```