Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 显示一个实例,其中a可能已经是字符串_Haskell_Show_Typeclass - Fatal编程技术网

Haskell 显示一个实例,其中a可能已经是字符串

Haskell 显示一个实例,其中a可能已经是字符串,haskell,show,typeclass,Haskell,Show,Typeclass,我正在研究一个类型,它是一个容器,基本上可以包含任何内容。大概是这样的: data Foo a = Foo [a] 我正在为这种类型制作一个Show实例 instance (Show a) => Show (Foo a) where show (Foo x) = concat $ map show x 这很好: show (Foo [1,2,3]) -- creates the string "123" show (Foo [True, False]) -- create

我正在研究一个类型,它是一个容器,基本上可以包含任何内容。大概是这样的:

data Foo a = Foo [a]
我正在为这种类型制作一个Show实例

instance (Show a) => Show (Foo a) where
       show (Foo x) = concat $ map show x
这很好:

show (Foo [1,2,3]) -- creates the string "123"
show (Foo [True, False]) -- creates the string "TrueFalse"
但是,有时foo中包含的“a”已经是一个字符串,因此不需要调用“map show x”。对字符串调用show的结果是,它在字符串周围放置“”

show (Foot ["A", "B"]) -- creates the string ""A""B""
-- what I'd like is the string "AB"

有没有办法为(Foo字符串)定义一个单独的Show实例

在标准Haskell中不能做这种事情。这是可以做到的,但这需要一些编译器的黑魔法。我们将使用一些GHC扩展

{-# LANGUAGE FlexibleInstances #-}

data Foo a = Foo [a]

instance (Show a) => Show (Foo a) where
    show (Foo x) = concat $ map show x

instance {-# OVERLAPS #-} Show (Foo String) where
    show (Foo x) = concat x
FlexibleInstances
允许我们打破通常的实例规则,编写
Show(Foo-String)
,而通常我们只能编写
Show(Foo-a)
。然后,我们用
{-#OVERLAPS#-}
注释前者,以抑制当
Show(fooa)
有多个重叠实例时发生的编译器错误。编译器非常聪明,可以选择更具体的实例,因此
Foo字符串
将始终调用第二个实例,而任何其他
a
Foo a
将调用第一个实例

用法示例:

*Main> Foo [1, 2, 3]
123
*Main> Foo [True, False]
TrueFalse
*Main> Foo ["A", "B"]
AB

这个款式好吗?可能不会。我建议重新考虑您的策略,为字符串大小写提供一个不同的函数(比如,
showFooString
),因为像上面那样编写代码可能会让用户感到困惑。但是如果你真的认为这是做你想做的事情的最好方式,那么就去做吧。请记住,您的代码实际上只能使用GHC进行编译。

整个业务闻起来相当可疑。
Show
的目的是作为
Read
的补充,因此,阅读所显示的内容应该是一种身份识别功能。显示包含字符串的数据时打印原始字符串无论如何都是错误的。字符串可能包含各种不适合人类消费的积垢,并且会严重破坏终端<代码>显示不仅添加了引号,而且避免了错误。我质疑你的说法,“调用‘地图显示x’是不必要的”。您建议的替代输出,
“AB”
,留下了歧义:除了示例输入之外,
Foo[“AB”]
Foo[,“A”,“B”]
都会产生相同的输出。