7

新しいデータ型を作成し、コンストラクターを大文字の定義ではなく小文字でのみ表示できるようにしたいとします。例えば:

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)

ここで、showの最初の出現は、新しい修正されたshow関数(印刷するたびに呼び出されます)を指定する必要がありますが、2番目の出現では、コンストラクター名から文字列に取得するために、通常派生バージョンのshowを指定します。

もちろん、これは機能しません(循環定義)。ghciには「show」という単語の私の別々の意味の手がかりがないためですが、両方のバージョンにshowという名前を付ける必要があるため、区別を知らせる方法がわかりません。 、1つ目は、printが呼び出すものであり、2つ目は、コンストラクター名から文字列を取得できる事前定義されたhaskell関数であるためです。私はもう試した

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

しかし、これは同じ循環定義に帰着します。少なくとも、ghciがループに陥っていることから私が推測することです。

コンストラクター名が大文字で始まる必要がある理由は理解していますが、小文字で表示しても問題はありませんか?たとえば、すべてのケースに対して個別にshow関数を定義できることはわかっていますshow Monday = "monday" show Tuesday = "tuesday"が、ここでは曜日のみを例として使用しており、実際のデータ型は64個のコンストラクターで構成されているため、どういうわけか別の方法でそれを解決します。

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

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

Jelle(Haskell初心者)

4

3 に答える 3

12

実際には、TypeableandDataクラスを使用してこれを行うことができます。

これを行うには、拡張機能が必要です。DeriveDataTypeable拡張機能をオンにする-XDeriveDataTypeableか、タイプを定義するファイルの先頭に次の行を配置してオンにします。

{-# LANGUAGE DeriveDataTypeable #-}

これで、必要なモジュールをインポートできます。

import Data.Data
import Data.Typeable

そして派生TypeableしてData

data Day = Monday | Tuesday | Wednesday| Thursday | Friday | Saturday | Sunday
     deriving (Typeable, Data)

toConstrこれで、コンストラクター表現を取得するために使用できます。

instance Show Day where
   show = strToLower . showConstr . toConstr

showDayしかし、単に関数や独自の型クラスを使用するのではなく、本当にやりたいかどうかについては、他の回答を参照してください。

于 2012-10-10T15:23:46.213 に答える
6

クラスのインスタンスは、Show出力をコピーして貼り付け、Haskellコードとして使用できるように機能することになっています。小文字のコンストラクターがある場合、これらはそのようには機能しません。彼らは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インスタンスではなく、ある種のきれいな印刷であるということです。あなたはあなた自身を転がすことができます

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
于 2012-10-10T13:44:24.673 に答える
3

同じデータ型に対してそれを実行できるかどうかはわかりませんが、私が見ることができる回避策は、次のように新しい型にラップすることです。

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

Dこれで、の代わりにtypeを使用できますDay

于 2012-10-10T13:31:28.183 に答える