LYH 7.6 型シノニム
新しい型を作る = ( 1 ) キーワード
型同義名(型シノニム)を作る = ( 2 ) キーワード
例えば、Stringは以下ように型シノニムとして定義されている。
type String = [Char]
電話帳を定義してみよう。
type PhoneNumber = String type Name = String type PhoneBook = [(Name, PhoneNumber)] pbook :: PhoneBook pbook = [ ("betty", "555-2938"), ("bonnie", "452-2928"), ... ] inPhoneBook :: ( 3 ) inPhoneBook name pnumber pbook = (name, pnumber) `elem` pbook
型シノニムの多相化
type AssocList ( 4 ) = [(k, v)]
とすることで、型引数を取ることができる。AssocListは ( 5 ) である。
以下の2つは同義
type ( 6 ) type IntMap v = Map.Map Int v
そこを左に行って、すぐ右へ
Either a b は( 7 )を2つとるデータ型である。
Left, Right はそれぞれ( 8 )である。
ghci> Right 20 ( 9 ) ghci> Left "w00t" ( 10 ) ghci> :t Right 'a' ( 11 ) ghci> :t Left True ( 12 )
Left True の型を評価すると ( 12 ) となっていることがわかる。Left ( 8 ) で作った値なので、1つ目の型引数は Bool に決まっているが、2つ目の型引数は ( 13 ) のまま残っている。これは、Nothing という値に ( 14 ) という型が付くのと同じ理屈である。
Nothing は何故失敗したかの情報を持つことはできない。これを持てるようにするために、普通は ( 15 ) 型の返り値を使う。ここで、( 16 ) は失敗が起こった場合に何であるかを伝えてくれる型、( 17 ) は、成功した計算の型である。したがって、エラーは ( 18 ) を、結果は ( 19 ) を使って表す。
ロッカーの割当のコードを書け。( 20 )
ロッカーを表すMapから暗証番号を検索する関数を作りたい。
関数が失敗するパターンが、( 21 ) と、( 22 ) の2通りあるので、( 23 ) 型で表すようにする。
実際に、暗証番号を検索する関数を作れ。( 24 )
解答
1. data
2. type
3. Name -> PhoneNumber -> PhoneBook -> Bool
4. k v
5. 型コンストラクタ
6. IntMap = Map.Map Int
7. 型引数
8. 値コンストラクタ
9 Right 20
10. Left "w00t"
11. Right 'a' :: Either a Char
12. Left True :: Either Bool b
13. 多相
14. Maybe a
15. Eihter a b
16. a
17. b
18. Left 値コンストラクタ
19. Right 値コンストラクタ
20.
ロッカーが使用中かどうかのフラグとロッカーへの暗証番号へのMapで表す。
import qualified Data.Map as Map data LockerState = Taken | Free deriving (Show, Eq) type Code = String type LockerMap = Map.Map Int (LockerState, Code)
21. ロッカーを他の誰かが使っている場合
22. ロッカー番号が存在しない場合
23. Either String Code
24.
lockerLookup :: Int -> LockerMap -> Either String Code lockerLookup lockerNumber map = case Map.lookup lockerNumber map of Nothing -> Left $ "Locker " ++ show lockerNumber ++ " doesn't exist!" Just (state, code) -> if state /= Taken then Right code else Left $ "Locker " ++ show lockerNumber ++ " is already taken!"