LoginSignup
5
5

More than 5 years have passed since last update.

行列プログラマ in Haskell

Last updated at Posted at 2016-11-30

行列プログラマに登場するPythonをひたすらHaskellでかいてく。対応するPythonコードは書籍にて確認いただきたい。

0.4.1 確率分布

> import Data.Map
> fromList [("heads", 1/2), ("tail", 1/2)] 
fromList [("heads", 1/2), ("tail", 1/2)]
  :: Fractional a => Map [Char] a

Pythonの辞書型に相当するものは Data.Mapかな。
他だいたい同じなので省略。

0.5.1 簡単な式

> 44 + 11 * 4 - 6 / 11
87.45454545454545

課題 0.5.1: Python を使用して、1 週間が何秒かを求めよ

> 7 * 24 * 60 * 60
604800

課題 0.5.2: Python を使用して、2304811 を 47 で割った余りを求めよ。ただし、% を使用しないこ と(ヒント://を用いる)。

> (\y x -> y - (y `div` x) * x) 2304811 47
25

% の代わりとしては remがある

文字列

> "This sentence is false."
"This sentence is false."

比較、条件、ブール値

> 5 == 4
False
> 4 == 4
True

haskellだとブール演算は && || not

> True && False
False
> True && not (5 == 4)
True

課題 0.5.3: ブール式を入力して、673 と 909 の和が 3 で割り切れるかどうかを調べよ。

問題の意味がわからず。。。省略

ghci内であれば :t で値の方を調べられる

> :t 4
4 :: Num t => t
> :t 4 == 4
4 == 4 :: Bool
> :t 
"4" :: [Char]
> :t 4 :: Float
4 :: Float

4の型は IntやFloatなど数字で扱える型になれることを出力している。
4をFloatとして使いたいなら型注釈をつければよい。

0.5.2 代入文

> mynum = 4+1

Haskellでは普通は再代入不可能だがghci上だと可能

> mynum = "Brow"

0.5.3 条件式

Haskellのifはelseが必須になる。

課題 0.5.4: −9 を x に、1/2 を y に代入する。以下の式の値を予想し、入力して予想を確認せよ。 2*(y+1/2) if x+10<0 else 2*(y-1/2)

条件は false 2 ** 0 で 1

> (\x y -> if x + 10 < 0 then 2**(y+1/2) else 2**(y-1/2)) (-9  :: Int) (1/2)
1.0

0.5.4 集合

> import Data.Set
> fromList [1+2, 3, 4]
fromList [3,4]

集合を表現するなら Data.Set

3が重複するのでひとつになってる。"a"は型が違うのでこのままでは一緒の集合にはできない。

> import Data.Set
> length(fromList ['a','b','c','a','c'])
3

濃度はlengthで取得できる。

集計

> import Data.Set
> sum(fromList [1,2,3])
6

集合の要素のテスト

> import Data.Set
> member 3 (fromList [1,2,3])
True
> member 4 (fromList [1,2,3])
False
> 4 `member` (fromList [1,2,3])
False
not . 4 `member` $ (fromList [1, 2, 3])
> True

集合の和集合、共通部分、差集合

> (fromList [1,2,3]) `union` (fromList [2,3,4])
fromList [1,2,3,4]
> (fromList [1,2,3]) `intersection` (fromList [2,3,4])
fromList [2,3]
> (fromList [1,2,3]) `difference` (fromList [2,3,4])
fromList [1]

集合の変更

> delete 2 . insert 4 . fromList $ [1,2,3]

fromList [1,3,4]

集合の内包表記

Setはモナドではななそうなので内包表記できそうにない。

> fromList [2*x | x <- [1,2,3]]
fromList [2,4,6]

課題 0.5.5: 集合 {1, 2, 3, 4, 5} に対する内包表記で、それぞれの整数の 2 乗を返すものを書け。

> fromList [x*x | x <- [1..5]]
fromList [1,4,9,16,25]

課題0.5.6: 集合{0,1,2,3,4}に対する内包表記で、それぞれの整数を2の指数に持つ値、即ち、20、 21、22 などを返すものを書け。

> fromList [2 ^ x | x <- [0..4]]
fromList [1,2,4,8,16]

> fromList [x*x | x <- toList (fromList [1,3] `union` (fromList [5,7]))]
fromList [1,9,25,49]
> fromList [x*x | x <- toList (fromList [1,3] `union` (fromList [5,7])), x > 2]
fromList [9,25,49]
> fromList [x*y | x <- [1..3] , y <- [2..4]]
fromList [2,3,4,6,8,9,12]

課題 0.5.7

> fromList [x*y | x <- [1..3] , y <- [5,7,11]]
fromList [5,7,10,11,14,15,21,22,33]

> fromList [x*y | x <- [1..3] , y <- [2..4], x /= y]
fromList [2,3,4,6,8,12]

課題 0.5.8

> fromList [x*y | x <- [2,4,8] , y <- [3,6,12]]
fromList [6,12,24,48,96]

課題 0.5.9

> [x | x <- [1,2,3,4] , y <- [3,4,5,6], x == y ]
[3,4]

0.5.5 リスト

> [1,1+1,3,2,3]
[1,2,3,2,3]

Haskellのリストの要素には制限があるのでHlistとか使うか、型を用意するかしないといけない。


> sum [1,1,0,1,0,1,0]
4
> foldl (+) (-9) [1,1,0,1,0,1,0]
-5

Haskellのsumに第2引数はないのでfoldlでかいてみた

0.5.10 評価した値がリスト [20,10,15,75] の要素の平均となる式を書け。

> (\xs -> sum xs / (fromIntegral . length $ xs)) [20,10,15,75]
30.0

求める結果が浮動小数になるように fromIntegralをつかっています。

リストの結合

++ で結合可能だけど、効率はいまいち

> [1,2,3] ++ [4,5]
[1,2,3,4,5]
> let mylist = [4,8,12]
> mylist ++ [4,5]
[4,8,12,4,5]
> mylist
[4,8,12]
> [[1,2,3], [4,5,6],[7,8,9]]

文字列と数値が混ざったリストはつくれないので数字だけにした。


すべてのリストを結合するのはsumではできないのでfoldMapをつかった。

> foldMap id [[1,2,3], [4,5,6],[7,8,9]]
[1,2,3,4,5,6,7,8,9]

リストの内包表記

> [2*x | x <- [2,1,3,4,5]]
[4,2,6,8,10]
>  [x*y | x <- [1,2,3] ,y <- [10,20,30]]
[10,20,30,20,40,60,30,60,90]

課題 0.5.11: リスト [’A’,’B’,’C’] 及び [1,2,3] に対するリスト内包表記で、その値が [文 字, 数字] の全ての可能な組み合わせから成るものを書け。即ち、その値は以下のようなものである。

[[’A’, 1], [’A’, 2], [’A’, 3], [’B’, 1], [’B’, 2],[’B’, 3],
[’C’, 1], [’C’, 2], [’C’, 3]]

> [(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)]

課題 0.5.12: LofL に数字のリストを要素に持つリストを代入したとしよう。このとき、そのリス ト全ての数値全部を足した合計を計算する式を書け。この式は次の形を持ち、内包表記を 1 つ持つ

> (\lofl -> sum [sum x| x <- lofl]) [[0.25, 0.75, 0.1], [-1,0], [4,4,4,4]]
16.1

インデックス指定によるリストの要素の取得

> let mylist = [1..4]
> mylist !! 0
1
> ["in", "the", "CI"] !! 1
"the"
> let l = [0,10..90]
> take 5 l
[0,10,20,30,40]
> drop 5 l
[50,60,70,80,90]
> map fst . filter (even . snd) $ zip l [0..]
[0,20,40,60,80]
> map fst . filter (odd . snd) $ zip l [0..]
[10,30,50,70,90]

スライスするいい方法がおもいうかばず。

アンパックによるリストの要素の取得

パターンマッチで代用

>  case [4*1, 4*2, 4*3] of [a,b,c] -> print a >> print b >> print c
4
8
12

リストの変更: =の左辺でのインデックス指定

Haskellでは原則リストの変更はできない。
再生成するしかないが効率は微妙なので、ここではおいておく。

0.5.6 タプル

> (1, 1+1, 3)
(1, 2, 3)

TBD

1.2 Pythonにおける複素数

Haskellで複素数をつかうには Data.Complexをimportする。
https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Complex.html

> import Data.Complex
> 0 :+ 3      -- 3j
> (0 :+ 3) * (0 :+ 3)
(-9.0) :+ 0.0
> import Data.Complex
> 1 :+ 3
> import Data.Complex
> (1 :+ 3) + (10 :+ 20)
11.0 :+ 23.0
> x = 1 :+ 3
> (x-1) ^ 2
(-9.0) :+ 0.0

Haskellの累乗計算の演算子は ^** がある
^が整数要で、**が浮動小数点要である

:++の優先順位は同じなので、注意

> 1 :+ 2 * 3
1 :+ 6
> 4*(0:+3)^^2
(-36.0) :+ 0.0

0:+とかくのがすこしめんどくさい

実部と虚部のとりだし

> realPart (1 :+ 3)
1
> imagePart (1 :+ 3)
3

型の確認

> :t (1:+2)
(1:+2) :: Num a => Complex a
5
5
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
5
5