2016-09-09 6 views
0

私はHaskellを初めて使いました。基本的なデータ型とコンストラクタを関数で見ています。私は以下のコードをやった関数を持つHas​​kellのデータ型とコンストラクタ?

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 

ラン罰金、しかし、それは過度に冗長ようだ - どのように私はそれを改善するために作ることができますか?

+0

(つまり、あなたのコンストラクタは、本質的に、入力のいくつかの再パッケージ以外の恒等関数であった。ある)多分これは一例ですが、あなたの 'DataSubject'タイプはなりません。私には非常に意味があります。 'DSInformation'と' DSConstruct'の違いは何ですか?同じタイプのコンストラクタはなぜですか? 'makeDataSubject'の代わりに' DSConstruct'だけで十分ではないのはなぜですか? – jberryman

答えて

4

data宣言のほとんどは、おそらく単純なtypeエイリアスにすることができます。これらの別名を持つ

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

DataSubjectのための2つのコンストラクタ間に有意差(脇レコード構文)はありません。 1つを取り除き、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 

あなたがここにスマートなコンストラクタを追加したいが、それは別の引数(ラップまたは開封された)、すでに同型までの戻り値ではありません1つの引数としてデータの各部分を取る必要がある場合があります。

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} 
1

残念ながら、あなたはハスケルの弱点の1つ、つまり記録システムにぶち当たっています。明示的に非構造化するのではなく、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となります。

関連する問題