69974


下記コードを Bar.hs という名前で保存

[code]

    data Person = User { name :: String, age :: Int }
    data Book = Book { name :: String }
    
    user = User { name = "A", age = 5 }
    
    main = do print $ name user
              print $ age user
    
[/code]

実行方法と結果

[code]

    % docker run -it --rm --name bar-haskell -v "$PWD":/tmp -w /tmp haskell:8 runghc Bar.hs
    
    Bar.hs:2:20: error:
        Multiple declarations of `name'
        Declared at: Bar.hs:1:22
                     Bar.hs:2:20
      |
    2 | data Book = Book { name :: String }
      |                    ^^^^
    
[/code]

上記のようになりました。

他のクラスベースの言語であれば、
`Userクラス`と`Bookクラス`のプロパティである`name`は衝突しないわけですが、Haskellだとどうすればいいんでしょう？
とくにクラスではなくて、JSONのようなハッシュでも別のJSONのキーとは衝突しないわけで、これだとHaskellで大きなプログラムはどのように作るのでしょうか？

おそらく同様のエラーで、コインに裏と表を定義、カードに裏と表を定義する下記も

[code]

    data Coin = Front | Back
    data Card = Front | Back
    
    Bar.hs:2:13: error:
        Multiple declarations of `Front'
        Declared at: Bar.hs:1:13
                     Bar.hs:2:13
      |
    2 | data Card = Front | Back
      |             ^^^^^
    
    Bar.hs:2:21: error:
        Multiple declarations of `Back'
        Declared at: Bar.hs:1:21
                     Bar.hs:2:21
      |
    2 | data Card = Front | Back
      |                     ^^^^
    
[/code]

というエラーです。


CC BY-SA 4.0
2020-08-29T07:58:42.233
69964
2020-08-30T01:37:30.830
2020-08-29T11:30:46.373
9008
9008
question
haskell
Multiple declarations of `name'


残念ながらこれは現在のHaskellの大きな弱点として知られています。  
現状の対策としては、moduleを分けるか、型名のプレフィックスをつける方法が一般的です。

ちなみに、JSONをパースした結果としてレコード型を返したい、といったケースにおいては、キーの名前を、レコードのフィールド名からプレフィックスを取り除いたものに変換する設定を加えたりします。  
詳しくは[デファクトスタンダードなJSONライブラリーであるaesonパッケージ](http://hackage.haskell.org/package/aeson-1.5.3.0/docs/Data-
Aeson.html#g:16)のドキュメントをご覧ください。

また、当然この問題を直そうという試みも進んでいます。経緯が複雑なので詳細は省きますが[拡張可能レコード |
haskell](http://lotz84.github.io/haskell/extensible-
record.html)や、原典として[overloaded record fields · Wiki · Glasgow Haskell Compiler
/ GHC · GitLab](https://gitlab.haskell.org/ghc/ghc/-/wikis/records/overloaded-
record-fields)をご覧ください。  
（※ですが、残念ながらこれらが解決するのはレコード型についての問題のみで、値コンストラクターの名前が被ってしまう問題についてはあまりみなさん関心がないようです。）

なお、[拡張可能レコード | haskell](http://lotz84.github.io/haskell/extensible-
record.html)でも触れられていますが、この問題を今手っ取り早く回避するために、サードパーティーのライブラリーを使うこともできます。  
私の体感では以下のものが比較的有名です。

  * <https://hackage.haskell.org/package/vinyl>
  * <https://hackage.haskell.org/package/extensible>

が、どうしても記述が独特であったり、GHCの型レベルプログラミングの機能を使わなければならなかったり、既存のレコードとの互換性がなかったりするので、使うときは慎重になりましょう。


CC BY-SA 4.0
2020-08-30T01:37:30.830
69974
2020-08-30T01:37:30.830
8007
69964
answer