这是一个当前失败的“hello world”尝试 - 我只是尝试使用以下代码在SqLite数据库上运行selectList
查询:
Database.Persist.Sqlite> runSqlite "database.sqlite" $ selectList [] [LimitTo 10]
<interactive>:46:1:
Couldn't match expected type ‘SqlBackend’
with actual type ‘PersistEntityBackend val0’
The type variable ‘val0’ is ambiguous
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
这几乎看起来太简单了搞砸......我哪里出错了?
答案 0 :(得分:6)
正如您可能已经知道的那样,Haskell的优势之一就是强力打字。持久性sqlite包通过要求表条目具有自己的数据类型,将其变为极端(在我看来,这是一件好事)。
例如,如果你有一个表格可以保存看起来像这样的水果
_______________________
|Fruit ID | Fruit Name|
-----------------------
| 0 | "apple" |
| 1 | "orange" |
-----------------------
并使用persistent-sqlite对此表进行查询,结果应存储在相应的Fruit类型中
data Fruit = Fruit { fruitName::String }
仅仅创建所述数据类型还不够,有一堆样板代码可以创建所需的类实例来实际使用它。您可以在持久模板库中使用模板Haskell magic来为您创建所有这些,而不是手动创建。
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Fruit
name String
deriving Show
|]
您的示例代码实际上是正确的,但缺少所有这些东西。此外,编译器甚至不知道尝试使用什么类型,因此,您收到的错误消息包含以下句子
The type variable ‘val0’ is ambiguous
这基本上就是编译器的说法,&#34;我不知道提取sql条目的类型。&#34;您可以使用显式类型指定
print (fruits :: [Entity Fruit])
最后,不幸的是,这段代码使用了一堆GHC扩展。将这些放在一起,这是一个更完整的最简单的例子。
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Control.Monad.IO.Class (liftIO)
import Database.Persist.Sqlite
import Database.Persist.TH
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Fruit
name String
deriving Show
|]
main :: IO ()
main = runSqlite "fruitDb.sqlite" $ do
fruits <- selectList [] [LimitTo 10]
liftIO $ print (fruits :: [Entity Fruit])
并且只是为了完成,这里是如何填充sqlite db来测试它。
> sqlite3 fruitDb.sqlite
sqlite> create table fruit (id, name);
sqlite> insert into fruit values (0, "apple");
sqlite> insert into fruit values (1, "orange");
答案 1 :(得分:3)
对于后人:我最近与The type variable ‘backend0’ is ambiguous
争论玩具Sqlite示例。编译器(正确地)无法确定我想用哪个backend
BaseBackend backend = SqlBackend
。
原来有三个:SqlBackend
,SqlWriteBacknde
和SqlReadBackend
。是的,对于第一个,如果你想知道它是否是一个错字,那么已解决的关联类型会自行解决。
你可以通过在某个地方放置一个显式类型签名来修复(在操作上粘贴一个类型的洞:: _
来获得提示),或者在你的操作中包含runMigration
调用,这会神奇地修复类型变量为SqlBackend
。