2016-03-21 11 views
0

でそのクラスの特定の値からデータクラスを取得私はハスケル

data Person = Person Name Surname [Projects] 
data Employees = Employees [Person] Salary 

二つの定義を持っていると私は、従業員に人のリストを使って、指定された名前から、対応する人物を取得し、いくつかを作りたいです対応する人の変化。たとえば、プロジェクトを実行する人のプロジェクトのリストにプロジェクトを追加したいとします。ハスケルでこれをどのようにすることができますか?

関数のシグネチャは、私達はちょうどパターンマッチングとmapを使用することによって最も直接的にこれを書くことができます

myfunction :: Employees -> Name -> Employees 
+1

これは法的なHaskellコードではありません、私はあなたを想定します'data Person = Person Name ... 'を意味します。型名とコンストラクタは大文字にする必要があります。また、あなたの質問はクラスとは関係がないようです(Haskellクラス - _type classes_ - はJavaのようにOOクラスとはかなり異なる)。 – leftaroundabout

+0

あなたは正しいです。悪い説明を申し訳ありません。ちょうど私がハスケルで新しく、私は言語に似たようなものです。 – qwerty

+0

問題はありませんが、それに応じて質問を編集してください。また、正確に何を望んでいるか(入力例とそれに対応する結果)についてさらに説明しています。 – leftaroundabout

答えて

1

ようにする必要があります。

この場合、ローカルの変更を行う小さなヘルパー関数を1つのPersonという値から作成し、mapのようなものを使用して、他のデータの束全体に変換を適用することがあります。だから我々は

updatePerson :: Name -> Person -> Person 
updatePerson targetName (Person name sur projects) 
    | targetName == name = Person name sur (NewProject : project) 
    | otherwise = Person name sur projects 

があるかもしれませんし、我々は一様にこれを行うには正しいことであるあなたのシナリオでは

myFunction :: Person -> Person 
myFunction name (Employee ps salary) = 
    Employee (map (updatePerson name) ps) salaray 

当社Employeeデータには、この変換を適用するために、もう少しコードを書くことができます。しかし、おそらく、これらのデータ構造の一部には多くアクセスすることになるので、それを少し最適化するのが理にかなっています!今、私はヘルパー関数でこれを書いたのではなく

myFunction name (Employee people salary) = Employee (map go people) salary 
    where go p | personName p == name = modifyProject ... p 
       | otherwise = p 

のようなものを書いて、その後

personName :: Person -> Name 
personName (Person name sur projects) = name 

modifyProjects :: ([Project] -> [Project]) -> Person -> Person 
modifyProjects f (Person name sur p) = Person name sur (f p) 

と:我々のデータ型を操作するために、いくつかのヘルパー関数を記述することによって、我々はより一般的なアプローチを取得する方法を見るかもしれませんパターンマッチングは、これらの関数、レコードを生成するためのHaskellの組み込み機能を使用することを示唆しているからです。

data Person = Person { _name :: Name 
        , _surname :: Surname 
        , _projects :: [Projects] 
data Employees = Employees {_people :: [Person], _salary :: Salary} 

そして、我々は

myFunction name e = e {_people = map go (_people e}} 
    where go p | _name p == name = p {_projects = New :: _projects p} 
      | otherwise = p 

ような何かを行うことができますが、今、これはHaskellの記録システムはで動作するように少し厳しいです、まだ不格好です。これは、実際には、「レンズ」を実装している狂った強力なライブラリの原型であり、汎用のコンビネータのキットを使用してこれらのレコードを変換するような機能を実装することができます。私はクールな何かをするためにスケールアップハスケルの例については、対応するレンズのコードを提供しますが、私は上記の3つの選択肢のいずれかが完全に罰金とそれほど複雑で

import Control.Lens 
data Person = Person { _name :: Name 
        , _surname :: Surname 
        , _projects :: [Projects] } 
data Employees = Employees {_people :: [Person], _salary :: Salary} 

makeLenses ''Person 
makeLenses ''Employees 

myFunction n e = 
    e & people.traverse.filtered pred.projects %~ (:) "New Project" 
    where pred person = person^.name.to (== n) 
+0

私の悪い説明にもかかわらず、何の不満もなくあなたの良い説明をありがとう... – qwerty