「Real World Haskell」読書メモ 3. 型定義、ストリーミング関数 再帰型

Real World Haskell 3. 型定義、ストリーミング関数 再帰型
再帰型の例にある List 型を使ってリストっぽいことをやってみた。

data List a = Cons a (List a)
             | Nil
               deriving (Eq, Ord, Show) 

cons a b        = Cons a b
car (Cons x _ ) = x
cdr (Cons _ xs) = xs

strToLs []     = Nil
strToLs (x:xs) = cons x (strToLs xs)

lsToStr Nil         = ""
lsToStr (Cons x xs) = x:lsToStr xs
ghci> cons 'a' Nil
Cons 'a' Nil

ghci> let abc =cons 'a' $ cons 'b' $ cons 'c' Nil
ghci> abc
Cons 'a' (Cons 'b' (Cons 'c' Nil))
ghci> car abc
'a'
ghci> cdr abc
Cons 'b' (Cons 'c' Nil)

ghci> let str = strToLs "Hello"                  
ghci> str
Cons 'H' (Cons 'e' (Cons 'l' (Cons 'l' (Cons 'o' Nil))))
ghci> car str
'H'
ghci> cdr str
Cons 'e' (Cons 'l' (Cons 'l' (Cons 'o' Nil)))
ghci> cdr $ cdr str
Cons 'l' (Cons 'l' (Cons 'o' Nil))
ghci> lsToStr str
"Hello"

deriving に Eq, Ord を追加したので比較が出来る。

ghci> let str = strToLs "Hello" 
ghci> let str2 = strToLs "Hello"
ghci> let str3 = strToLs "Hello!"
ghci> str==str2
True
ghci> str==str3
False
ghci> strToLs "1" > strToLs "2"  
False
ghci> strToLs "1" < strToLs "2"
True
ghci> str > str3
True
ghci> str< str3 
False

p61「猫の足跡のような囲み記事の説明」
組み込まれているリスト型と同じ。「多相型」だからいろんな型のデータが入るよ、ということ。

-- file: ch03/ListADT.hs
fromList (x:xs) = Cons x (fromList xs)
fromList []     = Nil

ghci> fromList [1,2,3]
Cons 1 (Cons 2 (Cons 3 Nil))

ghci> fromList "abc"  
Cons 'a' (Cons 'b' (Cons 'c' Nil))

ghci> fromList [Nothing,Just "hello"]
Cons Nothing (Cons (Just "hello") Nil)

Tree型

data Tree a = Node a (Tree a) (Tree a)
             | Empty
             deriving (Show)

-- Tree を表示する
showTree Empty = ""
showTree (Node a  b  c) = a ++ "\n" ++ (showTree b)  ++ (showTree c)

-- Node の要素を取り出す
treeNode  (Node node _    _)     = node
treeLeft  (Node _    left _)     = left
treeRight (Node _    _    right) = right

replace _ _ Empty = Empty
replace old new node
    | treeNode node == old  = Node new (replace old new (treeLeft node))
                                        (replace old new (treeRight node))
    | otherwise             = Node (treeNode node)
                                   (replace old new (treeLeft node)) 
                                   (replace old new (treeRight node))

treeMap _ Empty = Empty
treeMap f node  = Node (f (treeNode node))
                                   (treeMap f (treeLeft node)) 
                                   (treeMap f (treeRight node))

simpleTree = Node "parent" (Node "left child" Empty Empty)
                           (Node "right child" Empty Empty)
ghci> simpleTree                    
Node "parent" (Node "left child" Empty Empty) (Node "right child" Empty Empty)

ghci> putStr $ showTree $ simpleTree                                
parent
left child
right child
ghci> putStr $ showTree $ treeMap (\str->"<<"++str++">>") simpleTree
<<parent>>
<<left child>>
<<right child>>
data Tree a = Node a (Tree a) (Tree a)
             | Empty
             deriving (Eq, Ord, Show)

gtNode  (Node n _ _) = n
gtLeft  (Node _ l _) = l
gtRight (Node _ _ r) = r

-- データ挿入
insert :: (Ord a) => a -> Tree a -> Tree a
insert x node | node == Empty   = Node x  Empty Empty
              | gtNode node == x = node
              | gtNode node <  x = Node (gtNode node) (insert x (gtLeft node)) (gtRight node)
              | gtNode node >= x = Node (gtNode node) (gtLeft node) (insert x (gtRight node))

-- データ検索
search :: (Ord a) => a -> Tree a -> Maybe a
search x node | node == Empty   = Nothing
              | gtNode node == x = Just (gtNode node)
              | gtNode node <  x = (search x (gtLeft node))
              | gtNode node >= x = (search x (gtRight node))

lsToTree :: (Ord t) => [t] -> Tree t -> Tree t
lsToTree []     tree = tree
lsToTree (x:xs) tree = lsToTree xs (insert x tree)

t = lsToTree ["hello","world","good","morning","Hey !!"] Empty