Haskell入門(標準モジュール)

Data.Listモジュール

リストから重複する要素を取り除いた長さ

import Data.List

numUniques :: (Eq a) => [a] -> Int
numUniques = length . nub
*Main> numUniques [1,1,2,2,3,1]
3
*Main> nub [1,1,2,2,3,1]
[1,2,3]

Data.Listモジュールのインポート

Prelude> :m + Data.List
words

文字列を空白で区切ってリストにする

*Main> words "a bb ccc"
["a","bb","ccc"]
group

リストの要素の、隣接する同じ要素をまとめる

*Main> group [1,2,2,1,1,3]
[[1],[2,2],[1,1],[3]]
sort

リストの要素を昇順に並び替える

Prelude Data.List> sort [2,1,4,3]
[1,2,3,4]

文字列の中の各単語(スペースで区切られた文字列)の出現回数を求める

Prelude Data.List> "a b a c b"
"a b a c b"
Prelude Data.List> words it
["a","b","a","c","b"]
Prelude Data.List> sort it
["a","a","b","b","c"]
Prelude Data.List> group it
[["a","a"],["b","b"],["c"]]
Prelude Data.List> map (\ws -> (head ws, length ws)) it
[("a",2),("b",2),("c",1)]

関数にまとめると

import Data.List

wordNums :: String -> [(String, Int)]
wordNums = map (\ws -> (head ws, length ws)) . group . sort . words
tails

リストに対してtail関数を繰り返し実行する

*Main Data.List> tails "abc"
["abc","bc","c",""]
*Main Data.List> tails [1,2,3]
[[1,2,3],[2,3],[3],[]]
isPrefixOf

2つ目のリストが1つ目のリストで始まっているか

*Main Data.List> isPrefixOf "ab" "abc"
True
*Main Data.List> isPrefixOf "ab" "cabc"
False
any

述語とリストを受け取り、リストの中に述語を満たす要素が存在するか

*Main Data.List> any (==2) [1,2,3]
True
*Main Data.List> any (>4) [1,2,3]
False
*Main Data.List> any (=='a') "abc"
True

*Main Data.List> tails "abcd"
["abcd","bcd","cd","d",""]
*Main Data.List> any (isPrefixOf "bc") (tails "abcd")
True
*Main Data.List> any (isPrefixOf "ac") (tails "abcd")
False

ある文字列が別の文字列の部分文字列であるか判定する

import Data.List

isInList :: (Eq a) => [a] -> [a] -> Bool
isInList sand desert = any (isPrefixOf sand) (tails desert)
*Main Data.List> isInList "a" "abc"
True
*Main Data.List> isInList "b" "abc"
True
*Main Data.List> isInList "ab" "abc"
True
*Main Data.List> isInList "bc" "abc"
True
*Main Data.List> isInList "abc" "abc"
True
*Main Data.List> isInList "bcd" "abc"
False
*Main Data.List> isInList "cd" "abc"
False
*Main Data.List> isInList "d" "abc"
False

Data.Charモジュール

シーザー暗号

文字を文字コードに変換
*Main Data.List Data.Char> ord 'a'
97
*Main Data.List Data.Char> map ord "abcxyz"
[97,98,99,120,121,122]

文字コードを文字に変換
*Main Data.List Data.Char> chr 97
'a'

文字をシフト
*Main Data.List Data.Char> chr $ ord 'a' + 3
'd'
*Main Data.List Data.Char> chr $ ord 'b' + 3
'e'
import Data.Char

encode :: Int -> String -> String
encode offset msg = map (\c -> chr $ ord c + offset) msg

decode :: Int -> String -> String
decode shift msg = encode (negate shift) msg
*Main Data.List Data.Char> encode 1 "abcxyz"
"bcdyz{"
*Main Data.List Data.Char> decode 1 it
"abcxyz"