我正在嘗試使用 Haskell 的梁創建一個帶有簡單 where 子句的選擇查詢。從https://haskell-beam.github.io/beam/user-guide/queries/select/#where-clause,我相信這會奏效:
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Lib where
import Data.Int ( Int32 )
import Data.Word ( Word32 )
import Database.Beam
data FooT f
= Foo
{ _fooId :: Columnar f Int32
, _fooBar :: Columnar f Word32
}
deriving (Generic, Beamable)
instance Table FooT where
data PrimaryKey FooT f =
FooId (Columnar f Int32) deriving (Generic, Beamable)
primaryKey = FooId . _fooId
type Foo = FooT Identity
type FooId = PrimaryKey FooT Identity
deriving instance Show Foo
deriving instance Eq Foo
data BazDb f = BazDb
{ _bazFoos :: f (TableEntity FooT)
}
deriving (Generic, Database be)
bazDb :: DatabaseSettings be BazDb
bazDb = defaultDbSettings
selectFoosByBar :: HasQBuilder be => Word32 -> SqlSelect be Foo
selectFoosByBar bar = select $
filter_ (\foo -> _fooBar foo ==. bar) $
all_ $ _bazFoos bazDb
但我遺漏了一些重要的細節,所以我收到以下編譯錯誤:
<SNIP>/Lib.hs:42:22: error:
? Couldn't match type ‘QGenExpr QValueContext be QBaseScope Word32’
with ‘Word32’
Expected type: Word32
Actual type: Columnar (QExpr be QBaseScope) Word32
? In the first argument of ‘(==.)’, namely ‘_fooBar foo’
In the expression: _fooBar foo ==. bar
In the first argument of ‘filter_’, namely
‘(\ foo -> _fooBar foo ==. bar)’
? Relevant bindings include
foo :: FooT (QExpr be QBaseScope) (bound at src/Lib.hs:42:15)
selectFoosByBar :: Word32 -> SqlSelect be Foo
(bound at src/Lib.hs:41:1)
|
42 | filter_ (\foo -> _fooBar foo ==. bar) $
|
現在,錯誤資訊本身已經很清楚了,但我不太清楚的是==.我需要修改哪一邊以及如何修改。或者是缺少擴展名或型別注釋的問題。
uj5u.com熱心網友回復:
代碼的相關部分
selectFoosByBar bar = select $
filter_ (\foo -> _fooBar foo ==. bar) $
all_ $ _bazFoos bazDb
如果我們看==.你會看到(==.) :: SqlEq expr a => a -> a -> expr Bool,所以兩邊==.需要有相同的型別。
現在看看 (==.) 左邊是什么,我們看到了_fooBar foo :: Columnar f Word32。我們無法擺脫 Columnar 但我們可以將 bar 變成梁可以使用的東西val_:
selectFoosByBar bar = select $
filter_ (\foo -> _fooBar foo ==. val_ bar) $
all_ $ _bazFoos bazDb
請注意,這僅在我們洗掉型別注釋時才有效。使用型別注釋,它看起來像:
selectFoosByBar
:: (HasQBuilder be, HasSqlEqualityCheck be Word32,
HasSqlValueSyntax
(Sql92ExpressionValueSyntax
(Sql92SelectTableExpressionSyntax
(Sql92SelectSelectTableSyntax
(Sql92SelectSyntax (BeamSqlBackendSyntax be)))))
Word32) =>
Word32 -> SqlSelect be (FooT Identity)
selectFoosByBar bar = select $
filter_ (\foo -> _fooBar foo ==. val_ bar) $
all_ $ _bazFoos bazDb
我認為它需要這個巨大的注釋,以便 ghc 可以跟蹤be抽象出的后端。
編輯:如果我們啟用ConstraintKinds我們可以簡化注釋:
type MagicSql be =
HasSqlValueSyntax
(Sql92ExpressionValueSyntax
(Sql92SelectTableExpressionSyntax
(Sql92SelectSelectTableSyntax
(Sql92SelectSyntax (BeamSqlBackendSyntax be)))))
selectFoosByBar
:: (HasQBuilder be, HasSqlEqualityCheck be Word32, MagicSql be Word32) =>
Word32 -> SqlSelect be (FooT Identity)
uj5u.com熱心網友回復:
在違規行上,bar :: Word32(根據 的簽名selectFoosByBar)。
我認為 _fooBar foo是一個Columnar (something) Word32.
錯誤訊息說問題在于第一個 arg to ==.,但是查看 的型別==.,我認為您可以更改任一方以達成一致。
為什么是bar :: Word32?它具有直觀的意義;您正在嘗試按單詞過濾,因此 arg 應該是一個單詞。這表明,你可能想要做的事,以_fooBar foo獲得Word32它“出”。這可能是一個簡單的函式,但更有可能是相反的:以某種方式將您的==. bar操作提升到“查詢運算式”空間。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/399708.html
