如何限制函数的调用者在Haskell中传递串联字符串?

How to restrict the caller of the function from passing concatenated strings in Haskell?

提问人:mandark 提问时间:7/19/2017 最后编辑:mandark 更新时间:7/20/2017 访问量:60

问:

我正在查看 Bryan O'Sullivan 的名为 mysql-simple 的 mysql 的 haskell 客户端库。该库不允许用户使用串联字符串作为查询。

以下工作正常:

myQuery :: Query
myQuery = "SELECT id, name FROM users LIMIT 1"

但是,这失败了:

myQuery :: Query
myQuery = "SELECT id, name FROM users LIMIT 1" ++ ""

这是我在运行以下示例时遇到的错误:

do
  rows <- (query_ connection myQuery) :: IO [( Int , String)]
...


• Couldn't match expected type ‘Query’ with actual type ‘[Char]’
• In the expression: "SELECT id, name FROM users LIMIT 1" ++ ""
  In an equation for ‘myQuery’:
      myQuery = "SELECT id, name FROM users LIMIT 1" ++ ""

我的问题是,是什么让这种限制成为可能?

源代码中可以看出这是故意的,但我无法理解其背后的基本概念。是因为类型不是类型类的实例吗?另外,即使我连接了字符串,类型检查器也不应该推断生成的字符串可以用作?QueryStringQuery

提前致谢。

英语:SQL Haskell

评论


答:

5赞 Daniel Wagner 7/19/2017 #1

实际上,它确实允许将串联字符串作为查询。您只需要使用对查询进行操作的串联运算符:

myQuery :: Query
myQuery = "SELECT id, name FROM users LIMIT 1" <> ""

运算符特定于列表,而适用于 any(并且是 的实例,但不是列表类型)。(++)(<>)MonoidQueryMonoid

并回答你的另一个问题:a 永远不能用作 .我怀疑它可能来自扩展的信念,它允许您编写字符串文字并将它们解释为类型,而不是通过隐式应用它们。所以,例如StringQueryOverloadedStringsStringfromString

foo = "foo"

实际上是 的缩写。所以想象一下没有扩展的工作,你可以看到这两者之间的区别:foo = fromString "foo"

foo1 = fromString "bar" ++ fromString "baz"
foo2 = fromString ("bar" ++ "baz")

前者与你写的相对应;后者符合你的意思。

评论

0赞 Daniel Wagner 7/19/2017
(注:未经测试。我只是参考了文档,我没有安装软件包并实际检查它是否有效。
0赞 mandark 7/19/2017
看到你的回复后,我意识到我可以使用,因为来源也显示了它。如果已导入,也可以使用运算符。另外,您关于重载字符串的评论是正确的。我应该在问题中澄清这一点,但您的回答解释了我想知道的内容。多谢!mappendData.Monoid
0赞 Daniel Wagner 7/19/2017
@mandark 是的,并且是同义词,只要导入正确。mappend(<>)