haskell类型
一、源文件
介紹這個主要是因為下文很多代碼寫在源文件中,然后從ghci加載源文件進行測試。
創(chuàng)建一個文本文件,在其中輸入,并保存為add.hs文件
-- file: add.hs add x y = x - y打開ghci,加載剛才的文件(假設(shè)文件目錄為e:\haskell\add.hs),命令如下
ghci> :cd e:\haskell ghci> :load add.hs ghci> add 2 1二、語言特性
1. 延遲計算
表達式的值在需要用到的時候才被計算,比如在一個文本文檔中輸入如下,并保存為lazy.hs
-- file: lazy.hs add x y = if left || right then x + y else x -y left = True right = length [1..] > 0然后加載這個文件,并執(zhí)行 add 2 1,你會發(fā)現(xiàn)結(jié)果為3,而不是一直等待計算結(jié)果,說明right的值并沒有被計算出來。在很多其他語言中(如C#),邏輯或or被特殊處理,從而在左分量為真的時候?qū)τ曳至慷搪?#xff08;short-circuits),而haskell中,(||)運算符只是一個普通的函數(shù),并由于其延遲計算的特性,導致左分量為真的時候,右分量不被計算出來。當然了,haskell中也可以寫出短路的邏輯或函數(shù)
myOr l r = if l then l else rhaskell中還有一個稱作守衛(wèi)表達式的東東,上面說的myOr函數(shù)等價于
-- file: myOr.hs myOr l r | l = l myOr l r = r2. 類型
a) 函數(shù)類型
我們看take函數(shù)的類型
ghci> :type take take :: Int -> [a] -> [a]符號->是右結(jié)合的,即,類型說明等價于
take :: Int -> ([a] -> [a])b)代數(shù)數(shù)據(jù)類型
定義一個新的數(shù)據(jù)類型
-- file: Object.hs data ObjectProperty = Object Int String [String]deriving (Show)這個類型ObjectProperty與三元組(Int, String, [String])的元素相同,然而haskell認為它們類型不相同。如果要定義一個ObjectProperty類型變量,
ghci> let object = Object 0 "i" ["j", "k"] ghci> :type it it :: ObjectPropertyghci> :type Object
Object :: Int -> String -> [String] -> ObjectProperty
分析: Object是值(數(shù)據(jù))構(gòu)造器,ObjectProperty是對象類型,當然,也可以將對象類型與值構(gòu)造器寫成相同的,如
data Object = Object Int String [String]然而兩者僅僅是名稱相同而已。
?對于Object的元素分別為Int,String等類型,還可以自定義這些類型的同義類型,如下
-- file: Object.hs type ObjectId = Int type ObjectName = String type ObjectFields = [String] data Object = Object ObjectId ObjectName ObjectFields其實跟C++中的typedef關(guān)鍵字類似。
可以查看值構(gòu)造器Object的類型(是一個函數(shù))
ghci> :type Object Object :: ObjectId -> ObjectName -> ObjectFields -> Object?由于Object類型中元素是匿名的,可以通過匹配來獲取元素值,例如
ghci> let object = Object 0 "a" ["b", "c"] ghci> let Object x y z = object ghci> x 0 ghci> :type x x :: ObjectIdc)枚舉類型
-- file: Roygbiv.hs data Roygbiv = Red| Orange| Yellow| Green| Bluederiving (Eq, Show)其中Red、Orange等都為值構(gòu)造器
d) 記錄類型
前面簡單介紹過模式匹配。比如想內(nèi)窺一下Object(前文介紹的自定義代數(shù)數(shù)據(jù)類型)的內(nèi)部元素,則可以使用模式匹配,我們這次定義一個函數(shù)來獲取某個元素
getId (Object id _ _) = id getName (Object _ name _) = name getFields (Object _ _ fields) = fields然而這種方法還是顯得代碼大塊,看起來不爽。
可以定義記錄類型,如下
-- file: Object.hs data Object = Object {oid :: Int,oname :: String,ofields :: [String]} deriving (Show)這個類型定義其實跟下面的形式幾乎相同
-- file: Object.hs data Object = Object Int String [String]deriving (Show)getId :: Object -> Int getId (Object id _ _) = idgetName :: Object -> String getName (Object _ name _) = namegetFields :: Object -> [String] getFields (Object _ _ fields) = fields加載上面那個文件時,依然可以向以前那么使用Object類型
ghci> let object = Object 1 "az" ["b"]或者如下使用
ghci> -- order of elements can be variedghci> let object = Object{oid = 10, ofields = ["i"], oname="str"}
e)參數(shù)化類型
跟C#中的泛型類似。比如定義一個類型MyMaybe如下(注意與Prelude模塊中的Maybe區(qū)分,雖然功能類似)
-- file: Maybe.hs data MyMaybe a = MyJust a| MyNothing這里a就是參數(shù)化類型,a可以是String或者Int等,還可以是MyMaybe類型,即嵌套
ghci> let a = MyJust 1 ghci> let b = Just a ghci> :type b b :: Num a => Maybe (MyMaybe a)f)遞歸類型
haskell中的List類型與C#中的不同,它是一個遞歸類型,如下
-- file: MyList.hs data MyList a = Cons a (MyList a)| Emptyderiving (Show)這樣設(shè)計,使得對其進行遞歸計算方便。
?比如獲取List的首項,可以寫成如下
-- append to the former MyList.hs file endx = Empty y = Cons 1 xmyHead (Cons i j) = i myHead Empty = error "MyList.myHead: empty list"這里對Empty獲取首項會拋出一個錯誤,這樣處理還是可以的,我們不能返回Empty,否則跟myHead的第一個計算式的返回類型不同(第一個計算式返回類型為a,而Empty類型為MyList a)。不過,如果結(jié)合Maybe類型,或者上面介紹的MyMaybe類型,則可以避免拋出錯誤,從而使得代碼更好看些。處理如下
myHead (Cons i j) = MyJust i myHead Empty = MyNothing?
轉(zhuǎn)載于:https://www.cnblogs.com/sjjsxl/p/5413757.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
- 上一篇: 正则表达式-概要
- 下一篇: NPOI操作Excel