私は Haskell を初めて使用し、Persistent を ORM として使用して Scotty Web API を作成しようとしています。次のコードに問題があります。
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Account json
name String
description T.Text
deriving Show
...
|]
resource :: (PersistEntity a, PersistEntityBackend a ~ SqlBackend, ToJSON a, ToJSON (Entity a), FromJSON a) => String -> (Key a -> Key a) -> [SelectOpt a] -> Pool Connection -> S.ScottyM ()
resource url keyConv selectOpts pool = do
S.get (S.capture $ pluralize url) $ do
objects <- runDb pool $ selectList [] selectOpts
S.json $ map entityIdToJSON objects
S.get (S.capture $ url ++ "/:id") $ do
idParam <- S.param "id"
found <- runDb pool . getJust . keyConv . key $ idParam
S.json $ found
...
main :: IO ()
main = withSqlitePool "bla.db" 2 $ \pool -> do
S.scotty 3000 $ do
resource "/account" accountKey [Asc AccountId] pool
...
このresource
関数は、公開したい永続モデル オブジェクトの Scotty Web ルートを定義します。
によって定義された最初のルートresource
は、コレクション全体を取得します。たとえば、HTTP GET
to/accounts
はすべてのアカウントを返します。
によって定義された 2 番目のルートはresource
、ID によって特定のエンティティを取得します。たとえば、HTTP GET
to/account/1
は ID 1 のアカウントを返します。
関数はそのまま機能しますが、デフォルトの json シリアライゼーションに id が含まれていないのが気に入らないためentityIdToJSON
、get all ルートで使用しました。
ただし、entityIdToJSON
get by id ルートに含めようとすると、 の行でS.json $ found
、次のタイプのエラーが発生します。
Main.hs:61:31-35: Could not deduce (a ~ Entity e0) …
from the context (PersistEntity a,
PersistEntityBackend a ~ SqlBackend,
ToJSON a,
ToJSON (Entity a),
FromJSON a)
bound by the type signature for
resource :: (PersistEntity a, PersistEntityBackend a ~ SqlBackend,
ToJSON a, ToJSON (Entity a), FromJSON a) =>
String
-> (Key a -> Key a)
-> [SelectOpt a]
-> Pool Connection
-> S.ScottyM ()
at /home/poida/src/moneymoney-api-scotty/Main.hs:48:13-189
`a' is a rigid type variable bound by
the type signature for
resource :: (PersistEntity a, PersistEntityBackend a ~ SqlBackend,
ToJSON a, ToJSON (Entity a), FromJSON a) =>
String
-> (Key a -> Key a)
-> [SelectOpt a]
-> Pool Connection
-> S.ScottyM ()
at /home/poida/src/moneymoney-api-scotty/Main.hs:48:13
In the second argument of `($)', namely `found'
In the second argument of `($)', namely `entityIdToJSON $ found'
In a stmt of a 'do' block: S.json $ entityIdToJSON $ found
Compilation failed.
リソースに型制約を追加しようとしましたがEntity a
、事態が悪化しました。また、ハックに関するドキュメントを掘り下げてみましたが、読んでいるものすべてをよく理解していません。ドキュメントは、キーがそのキーとともにエンティティであることを示しているようです。
tl;dr - 私の問題は、エンティティを期待する Persistent の entityIdToJSON 関数で、Persistent の getJust 関数の結果である Key を使用しようとしていることです。
何か案は?