Haskell:`show`的变体,它不会在引号中包装String和Char

Joe*_*ams 3 haskell pretty-print

我想的变体show(我们称之为label),其行为就像show,只是它不换行StringS IN " "CharS IN ' '.例子:

> label 5
"5"
> label "hello"
"hello"
> label 'c'
"c"
Run Code Online (Sandbox Code Playgroud)

我尝试手动实现这个,但我碰到了一些墙.这是我尝试过的:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Label where

class (Show a) => Label a where
    label :: a -> String

instance Label [Char] where
    label str = str

instance Label Char where
    label c = [c]

-- Default case
instance Show a => Label a where
    label x = show x
Run Code Online (Sandbox Code Playgroud)

但是,因为默认大小写的类重叠,instance Label [Char]并且instance Label Char这些类型不适用于该label函数.

是否有提供此功能的库函数?如果没有,是否有解决方法来使上述代码工作?

C. *_*ann 5

上面的代码不起作用,因为只根据"head"选择实例,即类名后面的部分."上下文",即=>"显示" 之前的内容仅在之后进行检查.上下文可以消除实例并产生编译器错误,但不会导致编译器选择不同的实例.由于这种行为,重叠的实例可能存在歧义.

有编译器扩展可以让你编写更复杂的实例,但我怀疑你最好只编写你的Label类的单个实例.你有什么目的吗?根据你想要完成的任务,可能还有更特殊的用途.

您的示例代码非常简单 - 如果您愿意,只需添加OverlappingInstances扩展名即可使其无需进一步修改即可使用.使用OverlappingInstancesGHC可以容忍一些模糊性,只要有一个明显的"最具体"的实例.在您的代码中,具有特定类型的两个实例是特定的,因此不应该有任何问题.

TypeSynonymInstances为了更好的可读性,不妨在你加入时添加:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Label where

class (Show a) => Label a where
    label :: a -> String

instance Label String where label x = x

instance Label Char where label x = [x]

instance (Show a) => Label a where label = show
Run Code Online (Sandbox Code Playgroud)