fugafuga.write

日々のログ

すごいH本 part35

階層的モジュール

モジュールには階層構造を与えることができる。

Geometry.hsを分割する。Geometryディレクトリを作成する。

Geometry/Sphere.hs

module Geometry.Sphere
( volume
, area
) where

volume :: Float -> Float
volume radius = (4.0 / 3.0) * pi * (radius ^ 3)

area :: Float -> Float
area radius = 4 * pi * (raidus ^ 2)

Geometry/Cuboid.hs

module Geometry.Cuboid
( volume
, area
) where

volume :: Float -> Float -> Float -> Float
volume a b c = rectArea a b * c

area :: Float -> Float -> Float -> Float
area a b c = rectArea a b * 2 + rectArea a c * 2 + rectArea c b * 2

rectArea :: Float -> Float -> Float
rectArea a b = a * b

Geometry/Cube.hs

module Geometry.Cube
( volume
, area
) where

import qualified Geometry.Cuboid as Cuboid

volume :: Float -> Float
volume side = Cuboid.volume side side side

area :: Float -> Float
area side = Cuboid.area side side side

使う時はこうする

import qualified Geometry.Sphere as Sphere
import qualified Geometry.Cuboid as Cuboid
import qualified Geometry.Cube as Cube

所感

実際に何か作るような段階にならんとピンとこないっぽい。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る

すごいH本 part34

モジュールを作る

Geometry.hs

module Geometry
( sphereVolume
, sphereArea
, cubeVolume
, cubeArea
, cuboidArea
, cuboidVolume
) where

sphereVolume :: Float -> Float
sphereVolume radius = (4.0 / 3.0) * pi * (radius ^ 3)

sphereArea :: Float -> Float
sphereArea radius = 4 * pi * (raidus ^ 2)

cubeVolume :: Float -> Float
cubeVolume side = cuboidVolume side side side

cubeArea :: Float -> Float
cubeArea side = cuboidArea side side side

cuboidVolume :: Float -> Float -> Float -> Float
cuboidVolume a b c = rectArea a b * c

cuboidArea :: Float -> Float -> Float -> Float
cuboidArea a b c = rectArea a b * 2 + rectArea a c * 2 + rectArea c b * 2

rectArea :: Float -> Float -> Float
rectArea a b = a * b

使う時は、import Geometry とする

所感

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る

すごいH本 part33

今週のお題「2018年の抱負」

Data.Mapの話

連想リストを使うMapを使うということにする。Data.Mapはキーが順序付けされていることを利用して、効率よくキーを配置したりキーにアクセスしたりできる。

Data.MapPreludeData.Listと競合する名前をエクスポートしているので修飾付きインポートを行う。

import qualified Data.Map as Map

Data.Map.fromListを使って連想リストをMapに変換する

*Main> Map.fromList [(3,"shoes"),(4,"trees"),(9,"bees")]
fromList [(3,"shoes"),(4,"trees"),(9,"bees")]

元の連想リストに同じキーがあった場合は後のほうの要素が使われる。

連想リストをMapで実装する

phoneBook :: Map.Map String String
phoneBook = Map.fromList $
  [("betty", "555-2938")
  ,("bonnie1", "334-8878")
  ,("bonnie2", "334-8878")
  ,("bonnie3", "334-8878")
  ,("bonnie4", "334-8878")
  ]

実行結果

*Main> Map.lookup "betty" phoneBook
Just "555-2938"

phoneBookに新しい電話番号を挿入して新しいMapを作る

*Main> :t Map.insert
Map.insert :: Ord k => k -> a -> Map.Map k a -> Map.Map k a
*Main> Map.lookup "foo" phoneBook
Nothing
*Main> let newBook = Map.insert "foo" "123-5678" phoneBook
*Main> Map.lookup "foo" newBook
Just "123-5678"

電話番号がいくつあるか調べる

*Main> :t Map.size
Map.size :: Map.Map k a -> Int
*Main> Map.size phoneBook
5
*Main> Map.size newBook
6

電話番号を文字列でなく、Int のリストで表現したい。

string2digits :: String -> [Int]
string2digits = map digitToInt . filter isDigit

実行結果

*Main> string2digits "123-5678"
[1,2,3,5,6,7,8]

phoneBook に適用する

*Main> let intBook = Map.map string2digits phoneBook
*Main> :t intBook
intBook :: Map.Map String [Int]
*Main> Map.lookup "betty" intBook
Just [5,5,5,2,9,3,8]

1人が複数の電話番号を持っている場合に対応する。

phoneBook = Map.fromList $
  [("betty", "555-2938")
  ,("bonnie1", "334-8878")
  ,("bonnie1", "334-8877")
  ,("bonnie1", "334-8876")
  ,("bonnie1", "334-8875")
  ,("bonnie2", "334-8878")
  ,("bonnie3", "334-8878")
  ,("bonnie3", "335-8878")
  ,("bonnie4", "334-8878")
  ]

これだと、重複しているキーのペアは最後の要素が優先されてしまう。

*Main> phoneBook
fromList [("betty","555-2938"),("bonnie1","334-8875"),("bonnie2","334-8878"),("bonnie3","335-8878"),("bonnie4","334-8878")]

この問題を解決するにはData.Map.fromListWithを使う。この関数はキーの重複を削除しない。そのかわり、重複していた場合にどうするか決める関数を受け取る。

phoneBookToMap :: (Ord k) => [(k, String)] -> Map.Map k String
phoneBookToMap xs = Map.fromListWith add xs
  where add number1 number2 = number1 ++ ", " ++ number2

実行結果

*Main> Map.lookup "bonnie1" $ phoneBookToMap phoneBook
Just "334-8875, 334-8876, 334-8877, 334-8878"

所感

編集途中で投稿してしまってた。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る

すごいH本 part32

あけおめ。今年もHaskellやっていきます。

キーから値へのマッピング

連想リストでキーと値のペアを作成できる。

phoneBook = 
  [("betty", "555-2938")
  ,("bonnie1", "334-8878")
  ,("bonnie2", "334-8878")
  ,("bonnie3", "334-8878")
  ,("bonnie4", "334-8878")
  ]

キーで値を検索する関数を実装する

findKey :: (Eq k) => k -> [(k, v)] -> v
findKey key xs = snd . head . filter (\(k, v) -> key == k) $ xs

キーが見つからない場合、クラッシュする。

*Main> findKey "bonnie2" phoneBook
"334-8878"
*Main> findKey "foooooo" phoneBook
"*** Exception: Prelude.head: empty list

ここで、Maybe型を使う。

findKey :: (Eq k) => k -> [(k, v)] -> Maybe v
findKey [] = Nothing
findKey key ((k,v):xs)
  | key == k  = Just v
  | otherwise = findKey key xs

基底部を定義し、リストをhead,tailに分け、再帰を使っている。 しかし、再帰より畳み込みのほうがわかりやすい。

findKey :: (Eq k) => k -> [(k, v)] -> Maybe v
findKey key xs = foldr (\(k, v) acc -> if key == k then Just v else acc) Nothing xs

実行結果

*Main> findKey "bonnie2" phoneBook
Just "334-8878"
*Main> findKey "foooooo" phoneBook
Nothing

所感

Nothingが初期値なのに気づかず少し悩んでしまった。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る

2017ふりかえり

風呂の中でふりかえる。

 

転職

年始に転職せざるを得ない状況になった。転職活動を始めてすぐに決まったのは良かったし、Rails で仕事できているのでとりあえず合格というところ。年収は上がった。

 

技術

Ruby, Rails は業務で使ってはいるが、まだまだわからない部分がある。Elixirはじめ、関数型言語に興味をもちはじめた。現場ではスクラムもどきのようなことをやっていて、アジャイルを試行錯誤しながら実践できた。

 

音楽

ギターはバンドで弾くようになって練習量が増えたし、機材も揃って満足している。歌についてもコツが掴めそうでこの感じを継続していきたい。

 

健康

半年で6kgほど痩せた。筋トレとエアロバイクと食事を控えめにするだけで痩せた。

 

まとめ

Webエンジニアとしてはペーペーなりになんとかこなせたのではなかろうか。至らない部分があるのは当たり前なので精進あるのみ。歌とギターはもうちょっとレベル上げていきたい。

 

来年の目標

  1. とりあえずH本を終わらせる
  2. Elmでなんか作る
  3. 80kg -> 75kg まで体重を落とす
  4. Jazz のスタンダードを1曲練習する

 

以上、よいお年を。