Skip to content

Instantly share code, notes, and snippets.

@tan-yuki
Last active August 29, 2015 14:02
Show Gist options
  • Save tan-yuki/a5bd22974a4d7ff9935d to your computer and use it in GitHub Desktop.
Save tan-yuki/a5bd22974a4d7ff9935d to your computer and use it in GitHub Desktop.
2013/06/14(土)にOSSCafeでおこなったhaskell勉強会のメモ

振り返り

import

import Data.List

numUniques :: (Eq a) => [a] -> Int
numUniques = length . nub

nubData.Listの関数 Globalにロードされてしまう

Globalにロードさせたくない場合は

import qualified Data.List

numUniques :: (Eq a) => [a] -> Int
numUniques = length . Data.List.nub

spaceが前後にある.とspaceが前後にない.は意味が違う

Q. 各桁の数の合計が40となる最初の自然数は?

まずは各桁数の合計をたす関数を用意する

Data.ChardigitToIntshowを使用

Prelude> :m + Data.Char
Prelude Data.Char> digitToInt '2'
2
Prelude Data.Char> digitToInt '12345'

<interactive>:4:13: parse error on input `12345'
Prelude Data.Char> show 1234567
"1234567"
import Data.Char
import Data.List

digitSum :: Int -> Int
digitSum = sum . map digitToInt . show

findの利用

Data.List.find

Prelude Data.Char Data.List> :t find
find :: (a -> Bool) -> [a] -> Maybe a
firstTo40 :: Maybe Int
firstTo40 = find (\x -> digitSum x == 40) [1..]
  • [1..]は無限リスト
  • (\ ) はラムダ式

名前から電話番号を探す

名前から電話番号を探す

phoneBook = 
    [("betty",  "555-2938")
    ,("bonnie", "452-2928")
    ,("pasty",  "493-2928")
    ]

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

疑問点

  • ↑だと一致したあたいが見つかった後も探索をつづけちゃう
  • foldrを見ただけで再起だとわかるからこっちのほうがわかりやすいと書いているが、わかりにくくね?

実際

  • Data.List.lookupやれば一発
lookup "pasty" phoneBook
> Just "493-2928"

Data.Mapの利用

名前の衝突があるので、Data.Mppを使用するときは必ずqualifiedを使用

import qualified Data.Map as Map

phoneBook2 :: Map.Map String String
phoneBook2 = Map.fromList $ 
    [("betty",  "555-2938")
    ,("bonnie", "452-2928")
    ,("pasty",  "493-2928")
    ]
  • 先ほどの例よりもMapを使ったほうが速い

  • $: 右側の関数の評価を引数とする

    f, g: function
    x, y: value
    
    f x (g y)
    f x $ g y
    
    上記2つは同じ
    

    ( )が少ないとhaskellっぽいらしい

  • Data.Map.Map: 型

  • Data.Map.map: map関数(Data.Map.Mapが使えるようにしたmap関数)

Mapで重複したkeyを扱うには

(そもそもMapでそんなデータ扱おうとしてること自体が間違いなんじゃ・・・。)

Data.Map.fromListWith

Prelude Data.Char Data.List Data.Map> :t Data.Map.fromList
Data.Map.fromList :: Ord k => [(k, a)] -> Map k a
Prelude Data.Char Data.List Data.Map> :t Data.Map.fromListWith
Data.Map.fromListWith
  :: Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
phoneBook =  
    [("betty",  "555-2938")
    ,("betty",  "342-2492")
    ,("bonnie", "452-2928")
    ,("pasty",  "493-2928")
    ]
    
phoneBookToMap :: (Ord k) => [(k, String)] -> Map.Map k String
phoneBookToMap xs = Map.fromListWith add xs
    where add number1 number2 = number1 ++ ", " ++ number2
  
phoneBookToMap phoneBook
-- > fromList[("betty", "342-2492, 555-2938"), ("bonnie", "452-2928"), ("pasty",  "493-2928")]
  • これでもできるでー
phoneBookToMap :: (Ord k) => [(k, String)] -> Map.Map k String
phoneBookToMap xs = Map.fromListWith ((++) . (++ ", ")) xs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment