第二十一章:語言擴充套件和程式標註

夢飛發表於2017-03-11

之後的章節將介紹高階型別類和實際應用中的實踐。

1.語言擴充套件 Language Extension

  • 開啟某個語言擴充套件

    +原始碼頂部加入以下程式碼,它在該檔案內生效

    {-# LANGUAGE Extension #-}
    

    +在GHCi中使用 :set -XExtension,它在該會話內有效 +cabal配置中使用extension配置項,指定整個專案所有程式碼都開啟的語言擴充套件

  • 常用的語言擴充套件

    +TupleSections:可以把 表示式 (1,,3,)解析成\x y -> (1,x,3,y)

    +LamdaCase:簡化 \ x -> case x of 成 \case

    +MultiWayIf

    +BinaryLiterals:進位制數字書寫 0b/0B 2進位制,0x/0X 16進位制, 0o/0O 8進位制

    +BangPattern:用來方便書寫需要對引數進行嚴格求值的函式,如: someFun (!x, !y) = ..., 可以避免不必要的任務盒累積

    +Record puns:對使用記錄語法的資料作模式匹配時使用,NameFieldPuns

    +RecordWildCards:批量引入資料項的繫結

2.嚴格求值資料項

在Haskell中,可以在data宣告中使用!來標註某些資料項是嚴格求值的(總會被求值到弱狀態)

    data vec2 = vec2 !Double !Double

3.惰性模式

與上面的!對應,~起到相反的作用,稱為惰性模式 Lazy pattern, 也叫強制匹配模式 irrefutable pattern

    f :: (a, b) -> Int
    f ~(x, y) = x

    --f (1, 2) == 1
    --f()  執行報錯

4.程式標註 pragma

語言擴充套件的語法 {-# ... #-} 實際上是程式標註的一種形式,下面是一項常用的程式標註

  • 展開盒裝資料 UNPACK,如上面的vec2,我們可以進一步把資料中需要求值的資料項展開到資料的負載中

    data vec3 = vec3 {-# UNPACK #-} !Double
                     {-# UNPACK #-} !Double
                     {-# UNPACK #-} !Double
    

    好處:資料變得緊湊,更節省空間,資料訪問變快;

    缺點:資料共享變得困難,無法通過指標指向任務盒的方式建立惰性計算的資料

  • 內聯 INLINE

    用來控制程式編譯過程中函式內聯的發生,請盡力內聯該函式

    pred :: Int -> Bool
    {-# INLINE pred #-}
    
  • INLINABLE / NONLINE

    INLINABLE 標註該函式是可以內聯的;NONLINE 請永遠不要內聯該函式,往往配合一些unsafexxx函式使用

5.編譯選項

在使用GHC編譯選項時,可以通過命令列給GHC傳遞一些選項來控制編譯過程

ghc -fwarn-incomplete-patterns Main.hs

上面的-fwarn-incomplete-patterns告訴GHC對不完全的模式匹配輸出警告

下面是一些常用的引數

  • -O filename:設定編譯目標檔案的名稱
  • -prof : 開啟執行分析
  • -0x/0 :x是0,1,2,代表GHC的優化等級 optimization level,預設是0不優化
  • -vx/v:資訊輸出的等級,從0到4
  • -Wall:開啟全部的警告
  • -stastic:告訴連結器使用靜態函式庫連線最終的程式
  • -threaded:多執行緒執行時,用來控制編譯的程式在多核硬體上的執行

在cable配置裡,我們可以針對美國executable/libaray條目控制編譯過程的選項

6.執行分析 -prof

  • -fprof-auto
  • +RTS -p分析時間消耗
  • +RTS -h分析記憶體開銷
  • hp2ps (-c) *.hp 把分析檔案轉換為 .ps檔案

相關文章