2012-10-10 2 views
5

新しいデータ型を作成し、コンストラクタを大文字の代わりに小文字でのみ表示できるようにしたいとします。たとえば、次のように表示導出を追加することによりコンストラクタを小文字で表示する方法

data Day = Monday | Tuesday | Wednesday| Thursday | Friday | Saturday | Sunday 

は、GHCiのは「その他...月曜日、火曜日」としてそれらを印刷します

import Data.Char 

strToLower :: [Char] -> [Char] 
strToLower (x:xs) = toLower x : strToLower xs 
strToLower [] = [] 

instance Show Day where 
    show d = strToLower (show d) 

ショーの最初の発生が呼び出されます私の新しい改正ショーの機能を(指定する必要があります。それは「月曜日、火曜日...などの」表示するために取得するために私がショーの特別なインスタンスを作成しようとしました2回目は通常は派生したshowのものをコンストラクタ名からStringに変換するつもりです。

ghciは私の別の意味「ショー」には手がかりがないので、もちろんこれは機能しませんが(円形の定義)、両方のバージョンが必要とするために彼に区別を知らせる方法がわかりません最初のものはshowと呼ばれ、2番目のものは定義済みのhaskell関数なので、コンストラクタ名からStringを得ることができます。少なくともそれは私がループ内で立ち往生GHCiのから推測するものだ、私は

show d = strToLower ((showsPrec 0 d) "") 

を試してみたが、これはダウン同じ循環定義になります。

なぜコンストラクタ名は大文字で始める必要があるのか​​理解していますが、小文字の場合は問題ではないはずです。私はちょうど私のショー機能をすべてのケースごとに別々に定義できることを知っています。 show Monday = "monday"show Tuesday = "tuesday"などがありますが、ここでは例として曜日のみを使用しています。実際のデータ型は64個のコンストラクタで構成されていますので、何とか別の方法でそれを解決するほうがよりエレガントになると思います。

showのhaskell定義を掘り下げて、そのコードのコピーを変更することはできますか?これは私が考えることができる唯一の可能な解決策ですが、それができればそれを行う方法はわかりません。おそらくそうではありません。他のソリューションも非常に歓迎です!

は、お時間を割いていただき、ありがとうございます

Jelle(Haskellの初心者)

+4

なぜ 'showDay day = map toLower 'を書くことができないのですか? 'show'の代わりに' showDay'を使いますか? – dave4420

+0

他の答えに加えて、あなたの直接の質問に答えることは価値があるかもしれません(私の独自の 'show'を実装するためにどのように派生' show'を使うことができますか?)。 Haskellの基本的な規則は、各クラスが与えられた型のインスタンスを1つ以上持つことです。 –

答えて

9

独自のロールでした。

あなたは DeriveDataTypeable拡張を必要とするこれを行うには、 -XDeriveDataTypeableまたはあなたのタイプを定義するファイルの先頭に以下の行を入れてそれをオン:

{-# LANGUAGE DeriveDataTypeable #-} 

あなたが今、必要なモジュールをインポートすることができます。

import Data.Data 
import Data.Typeable 

そして、導出TypeableData

data Day = Monday | Tuesday | Wednesday| Thursday | Friday | Saturday | Sunday 
    deriving (Typeable, Data) 
単に代わりに showDay機能や、独自の型クラスを使用するのではなく、

instance Show Day where 
    show = strToLower . showConstr . toConstr 

をしかし、あなたが本当にしたいと思うかどうかについての他の回答を参照してください:

今、あなたは、コンストラクタ表現を取得するためにtoConstrを使用することができます。

+0

+1ありがとう..私はこれができるとは思わなかった.. – Satvik

+0

ありがとう!私はこのソリューションを好むのは簡単だし、 "偽の"(私の)ショー機能に頼らざるを得ずに、 "ショーブル"という純粋な概念を保持しているからです。再度、感謝します! – user1734761

+0

しかし、その出力は有効なHaskellコードではないので、このような 'Show'インスタンスは作成しません。しかしこれは 'showDay'やカスタムのtypeclassを定義する本当に良い方法です。+1。 - 関連しないノートでは、 'f $ g $ x'という形式の式を書くことは[廃止されました](http://stackoverflow.com/a/8618901/745903)です。代わりにg $ x'を使用します(この場合、 'show d = strToLower。showConstr $ toConstr d')。 – leftaroundabout

3

あなたが同じデータ型のためにそれを行うことができればよくは知らないが、私が見ることができる回避策はにそれをラップすることです

newtype D = D Day 
instance Show D where 
    show (D d) = strToLower $ show d 

などのnewtypeは今、あなたはタイプDの代わりDayを使用することができます。

+0

...「月曜日」の代わりに '(D月曜日)'を書く必要があります。 – dave4420

+0

@ dave4420彼は、 'show'の代わりにいくつかの他の関数を定義することはできますが、' show'インスタンスは他のライブラリ関数によって使用される可能性があるので、彼はそれだけでは変更できません。それは、私が話しているトレードオフです。それは回避策だと言いました。余分なコンストラクターを書くための費用はいくらかかかります。 – Satvik

6

クラスShowクラスのインスタンスは、出力をコピー・ペーストしてハスケル・コードとして使用できるように動作するはずです。現在、小文字のコンストラクタを使用している場合、これらはそのまま動作しません。彼らはあなたがおそらく好きではない冗長性をあなたに残しnewtypeアプローチ、もちろん

data DayInternal = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday 

newtype Day = Day DayInternal 
monday = Day Monday 
tuesday = Day Tuesday 
wednesday = Day Wednesday 
thursday = Day Thursday 
friday = Day Friday 
saturday = Day Saturday 
sunday = Day Sunday 

instance Show Day where 
    show (Day d) = strToLower $ show d 

、で動作します。 Template Haskellを使ってこれを自動的に構築することもできますが、それが本当に価値があるかどうかは疑問です。

私が本当に思っているのは、Showインスタンスではなく、かわいらしい印刷のようなものです。あなたは、あなたが実際にTypeableDataクラスを使用してこれを行うことができます

class MyNiceShow s where 
    myNiceShow :: s -> String 

data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday 
     deriving (Show) 

instance MyNiceShow Day where 
    myNiceShow d = strToLower $ show d 
+0

私はこれらの関数を(THでも)書くことは、パターンマッチングができず、これらのコンストラクタを書くことのほとんどがパターンマッチングに使用されると考えているからです。 – Satvik

+0

また、他のクラスのインスタンスを定義したり、関数を直接使用してデイブが提案したもの(myshow関数を書く)に従わなければならないので、showを書くための新しい型クラスを追加するのは無用です。 – Satvik

+1

いいえ、あなたは他のすべての型に対して 'Show'を使う方法で' MyNiceShow'を定義することができます(#OverlappinInstancesを使用しますが、ちょっと..)。 – Landei