IsString实例未自动转换为字符串

IsString实例未自动转换为字符串,string,haskell,typeclass,String,Haskell,Typeclass,我有一个类型a,它是IsStringtypeclass的一个实例 如果我使用类似 "foobar" :: a 一切正常 只要我使用返回字符串的函数,如 ("foo" ++ "bar") :: a 我得到一个编译错误告诉我 Couldn't match expected type ‘a’ with actual type ‘[Char]’ Expected type: a Actual type: String 注意,我有{-#LANGUAGE重载字符串#-}pragma 还有什么我应该做的

我有一个类型
a
,它是
IsString
typeclass的一个实例

如果我使用类似

"foobar" :: a
一切正常

只要我使用返回字符串的函数,如

("foo" ++ "bar") :: a
我得到一个编译错误告诉我

Couldn't match expected type ‘a’ with actual type ‘[Char]’
Expected type: a
Actual type: String
注意,我有
{-#LANGUAGE重载字符串#-}
pragma

还有什么我应该做的来解决编译错误吗?

类型类的思想是指定我们可以将
字符串
对象转换为这样的对象(使用
fromString::String->a
函数)。此外,通过启用
OverloadedStrings
pragma,我们还可以将
a
对象写入字符串文本(在这种情况下,通过调用
fromString
函数,这些
string
文本将透明地转换为
a
s)


但是请注意,
IsString
不会导致将
a
s转换回
String
s。此外,在
String
s上定义的函数不能用于此类实例(至少在不进行一些实现工作的情况下)

如果你写:

("foo" ++ "bar") :: a

Haskell将推导出您调用的
(++):[b]->[b]->[b]
,因此它知道这些字符串文本的类型是a
IsString[b]=>[b]
。这意味着
a~[b]
。由于您的类型可能不是列表,因此无法进行匹配。

IsString
并不意味着您可以对其应用各种操作。这只意味着我们可以将
字符串
转换为它,并且通过启用pragma,我们可以编写文本,然后将其透明地转换为此类对象。您的意思是
IsString
仅适用于硬编码字符串吗?没有任何实际是字符串的值?但是
a
实际上不是
字符串。但是,您可以使用
fromString
“foo”+“bar”
的结果强制转换为
字符串
“foo”+“bar”
已经是
字符串。我可以使用
fromString
String
转换为
a
,但我希望这会自动发生。就我所知,这只适用于
String
文本。这可能也是可取的,因为否则这将导致隐式类型转换,并可能导致相当未定义的行为。因为如果我们将其推广,我们有一个
a
,我们隐式地想将其转换为
d
,有两种方法(例如通过
f1::a->b
f2::b->d
,以及
g1::a->c
g2::c->d
),那么编译器应该选择什么呢?谢谢你的解释。现在有点道理了。感觉很奇怪,
“777”::a
工作,而
show 777::a
不工作,因为在这两种情况下,编译器都在将
[Char]
转换为
a
。换句话说,代码编译与否不仅仅取决于表达式的类型。。。这不是反对等式解析吗?字符串常量处理重载字符串的方式有点像数字常量的工作方式。常量
1
被重载,意味着
来自整数1
,因此您可以对任何类型的
Num
使用整数常量,默认为
integer
。类似地,您可以对任何类型的
IsString
使用字符串常量,默认为
string
。但是,这并不意味着您可以隐式地将任何
Integer
表达式转换为任何
Num
,而无需显式调用
fromIntegral
。斯林也是如此。(一些其他语言,如C++,确实提供了这种隐式转换)。如果你想这样做,最简单的方法是定义一个转换函数,比如<代码>数据。因此,在正确的
导入合格的
之后,
B.pack(“foo”+“bar”)
将通过testring
获得您的
。但是,为新类型重新实现函数通常会更有效(或者为什么要这样做?),因此您更可能编写
B.append“foo”“bar”
,然后编译器可以推断参数的正确类型。