# Thinking Functionally with Haskell勉強メモ: 第５章問題

### Exercise A

`Matrix Int`のすべての要素に１を足す関数：

```addOneToAll = map (map (+1))
```

`Matrix Int`のすべての要素の和：

```sumAll = sum . sum

sum :: Row Int -> Int
sum [] = 0
sum x:xs = x + sum xs
```

```addMatrix :: Matrix Int -> Matrix Int -> Matrix Int
```

Matrix multiplication:

```matMul :: Matrix Int -> Matrix Int -> Matrix Int
matMul m1 m2 = map (vecMatMul tm2) m1
where tm2 = transpose m2

vecMatMul m v = map (mulVecs v) m
mulVecs = sum . zipWith (*)
```

### Exercise B

```transpose :: [[a]] -> [[a]]
transpose [xs] = [[x] | <- xs]
transpose (xs:xss) = zipWith (:) xs (transpose xss)
```

`transpose [xs] = [[x] | <- xs]``transpose []`に変えるとしたら

```transpose [] = repeat []
```

`zipWith``xs`の要素分しか回さないので、停止ケースが無限リストでも大丈夫。

あるいは

```transpose ([]:xss) = []
transpose xss = map head xss :transpose (map tail xss)
```

### Exercise C

```any p = not . all (not p)
```

```any null = null . cp
```

### Exercise D

`sort`関数が存在すると仮定して、同じ要素が二回リストに登場するか調べる`nodups :: (Ord a) => [a] -> Bool`を定義せよ：

```nodups = check . sort
where check [x] = True
check (x:y:ys)
| x != y = False
| otherwise = check y:ys
```

### Exercise E

ダブった要素を取り除く関数`nub :: (Eq a) => [a] -> [a]`を定義せよ：

```nub [] = []
nul (x:xs) = x : nub (filter (/= x) xs)
```

```nub = nib . sort
nib [] = []
nib (x:xs) = x : dropWhile (==x) xs
```

### Exercise F

`takeWhile``dropWhile`を定義せよ：

```takeWhile :: (Eq a) => [a] -> [a]
takeWhile _ [] = []
takeWhile p (x:xs)
| p x = x : takeWhile p xs
| otherwise = []

dropWhile :: (Eq a) => [a] -> [a]
dropWhile _ [] = []
dropWhile p (x:xs)@xs'
| p x = dropWhile p xs
| otherwise = xs'
```

```words [] = []
words x:xs
| whitespace x = words (dropWhile whitespace xs)
| otherwise = (x : takeWhile (not whitespace) xs) : words (dropWhile (not whitespace) xs
```

### Exercise G

`minimum :: (Ord a) -> [a] -> a`の定義：

```minimum [x] = x
minimum (x:xs) = smaller x (minimum xs)
where smaller y z = z if y > z else y
```

### Exercise H

```solve = search . choices
search m
| not (safe m) = []
| complete m = [extract m]
| otherwise = process m
where process = concat . map search . expand1 . prune
```

`expand1`関数がすべてのマスが確定した`Matrix [Digit]`を引数に受け取るとエラーを起こすので、`prune`した結果はまず`complete m`とパターンマッチするか確認して、マッチしないものだけ`expand1`する必要がある。