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]
,因此它知道这些字符串文本的类型是aIsString[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”
,然后编译器可以推断参数的正确类型。