第十章:模組語法及cabal、Haddock工具

夢飛發表於2017-02-28

本章主要介紹如何書寫、管理和註釋程式模組。

1.模組語法

  • 模組:值、型別、型別別名、型別類等的集合

  • 在模組內部,通過import可以把其他模組中的值和型別等匯入到當前模組的環境中,從而被當前模組使用,同時模組也會匯出一些內部的值和型別等,使其他模組得以使用

  • 模組是程式碼複用的基本單元,一個模組對應一個原始檔

  • 一個程式由很多模組構成。一個完整的可執行程式應該包含一個叫做Main的模組

  • Main模組必須匯出main函式,他的型別必須是IO a,a 是任意一個具體型別

    Module Xxx.Yyy.Zzz (
        --定義了一個模組Xxx.Yyy.Zzz,也是import匯入時的名稱
        --括號指定了該模組的那些繫結/型別/型別類會被匯出
        --凡是當前作用域裡的繫結,無論是模組內部定義的還是import匯入的,都可以被模組匯出
             binding
        ,    module OtherModule
        --如果被匯入的模組裡所有的繫結和當前模組不衝突的話,可以直接重新匯出OtherModule裡的所有繫結
        ,    DataType(Constructor1, Constructor2...)
        --匯出資料型別及對應的建構函式
        --DataType()僅僅匯出資料型別,
        --使用..來代表所有的建構函式
        ,    ClassDef(classMethod1, classMethod2...)
        ,    ...
             ) where
    
    
       --匯入宣告
       import Aaa
       import Aaa.Bbb
       import Aaa.Bbb.Ccc (Type, value...)
       import qualified Aaa.Bbb.Ccc.Ddd as D
       import qualified Aaa.Bbb.Ccc.Eee as E hiding(Type, value)
       import OtherModule
    
    
       --下面開始正文
       ...
    
  • 除一些常用的模組外,推薦使用qualified關鍵字或選擇性匯入這兩種方式來避免名稱空間衝突

2.使用 cabal

  • cabal身兼包管理工具和自動化編譯工具的功能

  • Hackage http://hackage.haskell.org

  • cabal update 第一次使用時

  • cabal install containers -j --global
  • ghc-pkg管理全域性空間下安裝的函式庫
  • 一般建議只向全域性空間安裝一些非常常用的函式庫。
  • 對於專案相關的函式庫依賴,統統使用沙盒 sandbox來管理
  • 專案的cabal配置

    $ mkdir test
    $ cd test
    $ cabal sandbox init
    $ cabal init
    
  • cabal run根據剛剛cabal init 自動正常test.cabal檔案找到入口檔案Main.hs並編譯執行
  • cabal build 編譯整個專案
  • cabal clean 輕量之前的編譯結果
  • cabal sdist 生成可上傳發布的程式碼壓縮包
  • cabal upload Foo.tar.gz 上傳sdist命令打包好的程式碼包至Hackage

3.Haddock

  • Haddock工具可以根據原始碼中的註釋自動生成文件

    haddock Main.hs -o ./doc
    --根據Main.hs檔案裡的註釋生成文件到./doc目錄下
    
  • 掌握Haddock的寫法,除了能幫助我們閱讀使用Haddock格式書寫的程式碼註釋外,也可以幫助書寫規範的註釋

  • 一些常見的書寫規範

    --------------------------------------------------------
    -- |
    -- Module            :   xxx
    -- Copyright         :   xxx
    -- Licence           :   xxx
    -- ...
    --------------------------------------------------------
    
    
    --| 這是一個頂層繫結註釋
    square :: Int -> Int
    square x = x *x
    
    
    square :: Int -> Int
    -- ^ 在宣告後新增註釋
    square x = x *x
    
    
    {-|
    這是一段
    註釋
    -}
    
    
    square :: Int -> Int
    square x = x *x
    
    
    class Monad a where
      -- | 給return的註釋
      return :: a -> m a
      -- | 這是給>>=的註釋
      >>= :: m a -> (a -> m b) -> m b
    
    
    data T a b
    -- | 這是給建構函式C1的註釋
    = c1 a b
    -- | 這是給建構函式C2的註釋
    | c2 a b
    
    
    data T a b
    = c1 a b  -- ^這是給建構函式C1的註釋
    | c2 a b  -- ^ 這是給建構函式C2的註釋
    
    
    data R a b =
    C {  -- | 這是給資料項a的註釋
         a :: a,
         b :: b -- ^ 這是給建構函式C2的註釋
     }
    
    
     f :: Int    -- ^ 第二個引數註釋
       -> Float  -- ^ 第二個引數註釋
       -> IO ()  -- ^ 返回值的註釋
    

相關文章