簡體   English   中英

Haskells數據類型和帶有函數的構造函數?

[英]Haskells data types and constructors with functions?

我是Haskell的新手,正在研究基本數據類型和具有函數的構造函數。

我已經完成了以下代碼:

data Name = Name String deriving (Show)
data Age = Age Int deriving (Show)
data Iq = Iq Int deriving (Show)
data Language = Language String deriving (Show)
data DataSubject = DSInformation Name Age Iq Language | DSConstruct {name :: String, age :: Int, iq :: Int, language :: String} deriving (Show)

makeDataSubject :: DataSubject -> DataSubject --Take in info and output a record
makeDataSubject (DSInformation (Name n) (Age a) (Iq i) (Language l)) = (DSConstruct {name = n, age = a, iq = i, language = l})

main = do 
  let x = makeDataSubject $ (DSInformation (Name "Ron") (Age 34) (Iq 100) (Language "French"))
  putStrLn $ show x

運行良好,但是似乎太冗長了-我如何使它變得更好?

您的大多數data聲明都可能是簡單的type別名。

type Name = String
type Age = Int
type Iq = Int
type Language = String

使用這些別名, DataSubject的兩個構造函數之間沒有顯着差異(除了記錄語法)。 擺脫一個,並省去makeDataSubject (除非您希望封裝一些邏輯或防止模式匹配,否則您不需要智能構造函數即可執行操作。)

data DataSubject = DS { name :: Name
                      , age :: Age
                      , iq :: Iq
                      , language :: Language
                   } deriving (Show)

main = do 
        let x = DS { name="Ron", age=34, iq=100, language="French"}
        putStrLn $ show x

如果確實需要實類型,而不僅僅是別名,請使用newtype而不是data

newtype Name = Name String deriving Show
newtype Age = Age Int deriving Show
newtype Iq = Iq Int deriving Show
newtype Language = Language String deriving Show

data DataSubject = DS { name :: Name
                      , age :: Age
                      , iq :: Iq
                      , language :: Language
                      } deriving (Show)

main = do
         let x = DS { name=Name "Ron", age=Age 34, iq=Iq 100, language=Language "French"}
         putStrLn $ show x

您可能想在此處添加一個智能構造函數,但要讓它把每條數據作為一個單獨的參數(包裝的或展開的),而不是一個已經是同構的返回值的參數。 (也就是說,您的構造函數本質上是身份函數,而不是對輸入進行一些重新包裝。)

makeDataSubject :: String -> Int -> Int -> String -> DataSubject
makeDataSubject name age iq lang = DS {name=Name name, age=Age age, iq=Iq iq, language=Language lang}

要么

makeDataSubject' :: Name -> Age -> Iq -> Language -> DataSubject
makeDataSubject' name age iq lang = DS {name=name, age=age, iq=iq, language=lang}

不幸的是,您遇到了Haskell的弱點之一:記錄系統。 如果我們有某種表示法來表示subject.namesubject.age而不是顯式地進行銷毀,那將是很好的選擇,但是現在沒有很好的答案。 但是,GHC 8中即將進行的工作應該盡快解決該問題,並且在問題空間中有各種各樣的庫正在工作。 但是,對於這個問題,我們可以采用一個簡單的技巧: -XRecordWildcards

{-# LANGUAGE RecordWildCards #-}

module Main where

newtype Name = Name String deriving Show
newtype Age = Age Int deriving Show
newtype Iq = Iq Int deriving Show
newtype Language = Language String deriving Show

data DataSubject =
    DSInformation Name Age Iq Language
  | DSConstruct {name :: String, age :: Int, iq :: Int, language :: String}
  deriving Show

-- | Take in info and output a record
makeDataSubject :: DataSubject -> DataSubject
makeDataSubject (DSInformation (Name name) (Age age) (Iq iq) (Language language)) =
  DSConstruct {..}

main :: IO ()
main =
  print . makeDataSubject $ DSInformation (Name "Ron") (Age 34) (Iq 100) (Language "French")

通過分解為字段的名稱, {..}將選擇范圍內的那些綁定以自動填充字段。 絕對希望在編譯期間打開-Wall -Werror ,因為現在比以往任何時候都更容易拼寫錯誤並忘記填充字段,然后最終得到部分記錄(記錄系統的另一個缺陷)字段undefined

暫無
暫無

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

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