2013-10-04 18 views
5

私は単純なケースに対処するためのテンプレート・ハスケル/一部のレンズ装飾性といくつかの現在の慣行が存在しないことを確認しています:現在のベストプラクティスに関する記録グローバル名前空間

現在
data Person = Person { 
    name :: String, 
    ... 
} 

data Company = Company { 
    name :: String, 
    ... 
} 

私はインポートを適格化することによってグローバル名前空間を汚染しないようにしますが、レコードアクセスを不便にします。

import Person as P 

isFred :: Person -> Bool 
isFred p = (P.name p) == "Fred" 

実際にレコードフィールドにアクセスする方法はまだありますか?


@Emmanuel Touzeryの回答は、同じ地面をカバーする別の質問へのリンクがあるため、受け入れています。もう1つの質問は、「haskell名前空間」の検索では表示されません。他の答えに間違いはありませんが、私はそれを受け入れることができます。

溶液は、基本的には、単一の関数「名前」の各フィールド「HasName」のための1つの型クラスを作成するためのテンプレートハスケル、レンズ、型クラスおよび詳細が使用述べました。それぞれのデータ型は、独自の実装でそのクラスのインスタンスになります。それから私は完全に理解していないいくつかの魔法があります。

これは、レコードが基本的にタプルであり、そのタプルの2番目の要素を選択する通常の関数としてフィールドセレクタを実装しているからです。これらのフィールドセレクタ関数をエクスポートすると、それらはグローバル名前空間に入り、遅かれ早かれ(通常は早く)衝突します。

したがって、インポートは(上記の例のように)修飾するか、衝突しない名前を付けるか(名前の前に接頭辞を付けて最適化することをお勧めします)。

レンズのものは、2013年のように、すべての怒りで、その他のフィールドセレクタ/ゲッター+セッターの構成を可能にするレンズの基本的な考え方はあまりにも複雑ではないですが、実装は右の私の頭の上に行きます。レコードの


(HA!)私は(ちょうど偽のレコード名前空間へ5つの拡張)他のポストでのソリューションは、私が後だおそらく何ですが、それは魔法を大量に含んでいだと思います。

答えて

2

同様の質問が既に尋ねられた、とあなたはここでレンズを示唆答えを見ることができます: https://stackoverflow.com/a/17488365/516188

今のレンズはHaskellのコミュニティに大きな流行語です、彼らは間違いなく彼らの用途があり、彼らこの名前空間問題の解決策の一部である可能性があります。しかし、現在、問題を解決するためだけにレンズを使用している人々は、私が思うには少数です。 Nikita Volkovが述べたように、この時点では、適格輸入品とプレフィックスが典型的な解決策になるだろう。

UPDATE:約this other optionが見つかりましたが、まだ確定されていませんが、お約束しているようです。ここにはthis blog postの末尾に記載されています。

6

は、一般的に唯一の2つの方法がありますが、残念ながらコミュニティでそれらについてのconsesusはありません。

  1. は、別々のファイルで彼らに対しての機能を使用してレコードを置き、のように完全な別名で修飾して使用します。

    import qualified Data.Person as Person; import Data.Person (Person) 
    
    isFred :: Person -> Bool 
    isFred p = (Person.name p) == "Fred" 
    

    このアプローチは、ファイルのクラスが1つしかないJavaなどの言語と同じです。

  2. 場所は、同じファイル内のレコードが、レコードの名前のフィールド名の前にしながら、例えば:

    data Person = Person { 
        personName :: String, 
        personAge :: Int, 
        ... 
    } 
    
  3. レンズ・ライブラリの

はいずれも、この問題に近づきます。

+0

これらのどちらも本当に問題に対処していません。プレフィックスの種類が異なるだけです。メソッド/属性の名前空間はクラス/オブジェクトに限定されているので、オブジェクト指向では問題にはなりません。これは一般に、グローバルなクラス名前空間だけです。とにかくおかげで - 私はこれで見つけることができた最後の議論は約18ヶ月だった。 –

+1

より良い記録システムの実装についての話は、永遠に似ています。たくさんの提案された解決策があります。問題を解決するハスケルの方言もある(http://en.wikipedia.org/wiki/Frege_(programming_language)#Records)。残念ながら、それらのどれかが実装されるのを待たなければなりません。 –

+0

ええ - 私は古い(頭上で)議論のいくつかを徘徊しました。何年も前に90%の解決策をとるのではなく、今から10年後の100%解決策を待っているような状況の1つです。 –

0

ここに私のアプローチがあります。実際には、レコード名をエクスポートする必要がないことが多いので、名前空間の汚染はモジュール自体の中での懸念に過ぎません。だから私はそうのように、短いプレフィックス、型クラスの通常最初の文字を使用します。私は他のモジュールが直接フィールドへのアクセスを許可する必要があります状況で

data Person = Person { 
    pName :: String, 
    ... 
} 

data Company = Company { 
    cName :: String, 
    ... 
} 

、それは通常、1つまたは2つのフィールドです。そして、しばしば私は読み取りアクセスを許可したいだけです。その場合、私は少し創造的かもしれません。おそらくこのようなものでしょう。

module Whatever 
    { 
    Person, 
    personName, 
    Company, 
    companyName, 
    ... 
    } 

data Person = Person { 
    pName :: String, 
    ... 
} 

data Company = Company { 
    cName :: String, 
    ... 
} 

personName :: Person -> String 
personName = pName 

companyName :: Company -> String 
companyName = cName 
+0

ええ、いつもフィールド名の前に付けることができます。 Haskellのレコードを外部の構造とマッチさせず、コードを醜いものにするという犠牲を払って、この問題を回避します。 –

関連する問題