如何以小写“显示”构造函数

时间:2012-10-10 13:19:44

标签: haskell show

假设我想创建一个新的数据类型并使构造函数可以显示,只是小写而不是大写的定义。例如:

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函数(每次打印时都会调用),而对于第二次我打算通常派生的show版本,从构造函数名称到String。

当然这不起作用(循环定义),因为ghci对我对“show”这个词的单独含义没有任何线索,但我无法弄清楚如何让他知道这个区别,因为两个版本需要被命名为show,第一个因为那是打印调用的,第二个是因为它是一个预定义的haskell函数,它可以给我一个构造函数名称的字符串。我试过了

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

但这归结为相同的循环定义,至少我认为ghci陷入了循环中。

我理解为什么构造函数名称需要以大写字母开头,但显示小写字母应该不是问题,是吗?我知道我可以单独为每个案例定义我的show函数,例如show Monday = "monday" show Tuesday = "tuesday"等,但我只使用一周中的日子作为示例,我的真实数据类型由64个构造函数组成,所以我认为以某种方式解决它会更优雅。

是否可以深入了解show的haskell定义并更改该代码的副本?这是我能想到的唯一可能的解决方案,但我不知道该怎么做,如果可能的话。可能不是。所以其他解决方案也非常受欢迎!

感谢您抽出宝贵时间,

Jelle(Haskell初学者)

3 个答案:

答案 0 :(得分:11)

您实际上可以使用TypeableData类来完成此操作。

要执行此操作,您需要DeriveDataTypeable扩展程序,使用-XDeriveDataTypeable打开它,或者将以下行放在定义您的类型的文件的开头:

{-# LANGUAGE DeriveDataTypeable #-}

您现在可以导入所需的模块:

import Data.Data
import Data.Typeable

并衍生出TypeableData

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

现在您可以使用toConstr来获取构造函数表示:

instance Show Day where
   show = strToLower . showConstr . toConstr

但请参阅其他答案,了解您是否真的想要,而不是简单地使用showDay函数或您自己的类型类。

答案 1 :(得分: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

答案 2 :(得分:3)

嗯,不知道你是否可以为相同的数据类型做到这一点,但我能看到的解决方法是将其包装成新类型

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

现在,您可以使用D类型代替Day