簡體   English   中英

在 Haskell 中推導是什么/意味着什么?

[英]What does deriving do/mean in Haskell?

堆棧溢出推導的定義是:

“在 Haskell 中,派生實例是與數據或新類型聲明一起自動生成的實例聲明。派生實例聲明的主體在語法上是從關聯類型的定義中派生的。”

老實說,我真的不明白其中的任何一個。

以下代碼摘自:鏈接

data BaseballPlayer = Pitcher 
                        | Catcher
                        | Infielder
                        | Outfielder
                        deriving Show

barryBonds :: BaseballPlayer -> Bool
barryBonds Outfielder = True

barryInOf = print(barryBonds Outfielder)

我的問題是,派生語句在這種特定情況下做什么,以及派生語句一般做什么?

簡而言之:

deriving自動實現一些 Haskell 類型類的函數,例如ShowEq 這不能用任意類型類來完成,但deriving工作的類型類對於自動實現來說足夠簡單。

Show類型類定義了如何將數據類型表示為String函數。

更廣泛:

你熟悉類型類嗎?

https://www.haskell.org/tutorial/classes.html

類型類類似於 Java 中的接口:它們定義了一些函數,任何想要使用這些函數的數據類型都可以實現這些函數。

例如,假設我們有一個這樣的類:

class Comparable a where
    lessThan :: a -> a -> Bool
    equalsTo :: a -> a -> Bool

當心字的class 它意味着 Haskell 設置中的類型類,而不是您在面向對象語言中聽到的典型“類”。 這里的a是一種填充類型,類似於您期望模板在 C++ 中的工作方式和泛型在 Java 中的行為方式。

假設我們定義了一個數據類型如下:

data Color = Red | Green | Blue

為了使ComparableColor工作,我們實現了一個Comparable instance

instance Comparable Color where
    lessThan Red   Green = True
    lessThan Red   Blue  = True
    lessThan Green Blue  = True
    lessThan _     _     = False

    equalsTo Red   Red   = True
    equalsTo Green Green = True
    equalsTo Blue  Blue  = True
    equalsTo _     _     = False

粗略地說,這現在允許您相互“比較” RedGreenBlue 但是有沒有辦法讓 GHC 自動猜測這是您想要的確切“順序”?

退后一步,類型類Show具有類似的結構:

https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Show.html#Show

class  Show a  where
    showsPrec :: Int -> a -> ShowS
    show      :: a   -> String
    showList  :: [a] -> ShowS

    showsPrec _ x s = show x ++ s
    show x          = shows x ""
    showList ls   s = showList__ shows ls s

需要注意的是,類型類中的函數可以相互定義。 事實上,我們也可以很容易地做到:

class Comparable a where
    lessThan :: a -> a -> Bool
    equalsTo :: a -> a -> Bool

    greaterThan :: a -> a -> Bool
    greaterThan lhs rhs = not (lessThan lhs rhs && equalsTo lhs rhs)

然而,關鍵在於:對於任意用戶定義的類型類,當您嘗試將類型類與諸如ColorBaseballPlayer之類的數據類型相關聯時,GHC 不知道它們的功能應該如何實現。 對於某些類型類,例如ShowEqOrd等,其功能足夠簡單,GHC 可以生成默認實現,您當然可以自己覆蓋這些實現。

事實上,讓我們嘗試編譯以下內容:

data Color = Red | Green | Blue deriving (Comparable)

我得到的結果是這樣的:

test.hs:9:43:
    Can't make a derived instance of ‘Comparable Color’:
      ‘Comparable’ is not a derivable class
      Try enabling DeriveAnyClass
    In the data declaration for ‘Color’

當然,一些GHC擴展可以用來擴展的電源deriving ,但這是另一天:)

在這種特定情況下,它會為您的類型生成一個Show實例,如下所示:

instance Show BaseballPlayer where
    show Pitcher    = "Pitcher"
    show Catcher    = "Catcher"
    show Infielder  = "Infielder"
    show Outfielder = "Outfielder"

通過這種方式, BaseballPlayer類型的值可以轉換為字符串,例如通過print

選擇字符串,使其成為有效的 Haskell 表達式,一旦求值,就可以重建原始值。

一般情況有點復雜,但遵循相同的想法:將值轉換為 Haskell 表達式字符串。 例如

data T = T Int (Maybe Bool) deriving Show

將制作實例,以便

show (T 1 Nothing) = "T 1 Nothing"
show (T 2 (Just 3)) = "T 2 (Just 3)"

注意在最后一種情況下括號也是如何生成的。 這是使用showsPrec類成員完成的,但這並不重要。

派生意味着您的數據類型能夠自動“派生”某些類型類的實例。 在這種情況下BaseballPlayer派生Show這意味着我們可以使用任何需要Show實例來與BaseballPlayer一起工作的函數。

自動派生使您更容易避免樣板。 最常見的自動派生類型類是ShowEq ,因為編譯器可以為這些類型類生成非常合理的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM