Haskell type system exercises

本文有 2681 字,大约需要 6 分钟可以读完, 创建于 2012-03-14

Haskell的类型系统是强类型的,并且没有任何强制类型转换。所有的类型检查均在编译器做检查。定义新的数据类型之后,即使它们内在的数据结构完全一样,也是完全不同的数据类型,不能混用。

Maybe 类型

Maybe类型是有一种基于已有类型的二次封装类型,用于表述可能为空的抽象类型,用于支持类似于 C++/Java 中的模板机制,不过Haskell的类型系统表达能力比一般语言中的模板强大很多。

Maybe a = Just a | Nothing

新类型定义

  • 可以采用data关键字来定义,=后边第一个标志符是其构造函数,用于构造新类型的实例对象。也可以用type来建立类型别名。不同的类型别名对用的新类型是不能互相转换的。

  • 类型定义中可以用 | 来指定多个构造函数,这些构造函数最终都会生成同样类型的实例。

  • 类型定义中,可以用record语法来提高可读性。

练习题解法

toList 的实现:

data List a = Cons a (List a)
            | Nil
              deriving (Show)

fromList (x:xs) = Cons x (fromList xs)
fromList []     = Nil

-- my solution --
toList (Cons x (xs)) = x : toList xs
toList Nil = []

运行结果:

Prelude> :load ListADT.hs 
[1 of 1] Compiling Main             ( ListADT.hs, interpreted )
Ok, modules loaded: Main.
*Main> let alist = fromList [1..12]
*Main> alist
Cons 1 (Cons 2 (Cons 3 (Cons 4 (Cons 5 (Cons 6 (Cons 7 (Cons 8 (Cons 9 (Cons 10 (Cons 11 (Cons 12 Nil)))))))))))
*Main> toList alist
[1,2,3,4,5,6,7,8,9,10,11,12]

用Maybe类型实现的模板树

已经给出的实现代码:

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

simpleTree = Node "parent" (Node "left child" Empty Empty)
                           (Node "right child" Empty Empty)
  • 采用Maybe的实现一:
data MyTree a = MyNode a (Maybe (MyTree a)) (Maybe (MyTree a))
                deriving (Show)

mySimpleTree = MyNode (Just "parent") (Just (MyNode (Just "left child") Nothing Nothing))
                                (Just (MyNode (Just "right child") Nothing Nothing))
  • 采用Record语法提高可读性:
data MyTreeRecord a = MyTreeRecord {
          parentNode  :: a
        , leftChild   :: Maybe (MyTreeRecord a)
        , rightChild  :: Maybe (MyTreeRecord a)
} deriving (Show)

anotherSimpleTree = MyTreeRecord {
    parentNode  = "parent"
   ,leftChild   = Just MyTreeRecord {
            parentNode  = "left child",
            leftChild   = Nothing,
            rightChild  = Nothing
        }
   ,rightChild  = Just MyTreeRecord {
            parentNode  = "right child",
            leftChild   = Nothing,
            rightChild  = Nothing
        }
}

运行结果:

Prelude> :load Tree.hs 
[1 of 1] Compiling Tree             ( Tree.hs, interpreted )
Ok, modules loaded: Tree.
*Tree> simpleTree 
Node "parent" (Node "left child" Empty Empty) (Node "right child" Empty Empty)
*Tree> mySimpleTree 
MyNode (Just "parent") (Just (MyNode (Just "left child") Nothing Nothing)) (Just (MyNode (Just "right child") Nothing Nothing))
*Tree> anotherSimpleTree 
MyTreeRecord {parentNode = "parent", leftChild = Just (MyTreeRecord {parentNode = "left child", leftChild = Nothing, rightChild = Nothing}), rightChild = Just (MyTreeRecord {parentNode = "right child", leftChild = Nothing, rightChild = Nothing})}
*Tree> 

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...