如何在 IHP 脚本中重用 IHP 类?
How to reuse IHP classes in a IHP script?
我使用 IHP(haskell 网络框架)创建了一个网络应用程序。现在我想创建一个 IHP 脚本来将一些外部数据加载到我的数据库中。然而,我从 Prelude 中得到了很多导入冲突,但不是我期望的类型。
#!/usr/bin/env run-script
module Application.Script.DataLoader where
import Application.Script.Prelude hiding (decode, pack, (.:))
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import Data.Text (pack)
import qualified Data.Vector as V
import Control.Monad (mzero)
instance FromNamedRecord Product where
parseNamedRecord r = Product def <$> r .: "title" <*> r .: "price" <*> r .: "category" <*> pure def
run :: Script
run = do
csvData <- BL.readFile "~/tender/data/Boiler-en-kookkraan_Boiler.csv"
case decodeByName csvData of
Left err -> putStrLn $ pack err
Right (_, v) -> V.forM_ v $ \ p ->
putStrLn $ (get #title p) ++ ", " ++ show (get #price p) ++ " euro"
我的 Product
架构如下所示:
CREATE TABLE products (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
title TEXT NOT NULL,
price DOUBLE PRECISION NOT NULL,
category TEXT NOT NULL
);
有没有一种方法可以将我创建的类型用作数据对象,例如读取我的 csv 到?
[更新输出]
Application/Script/DataLoader.hs:12:26: error:
• Couldn't match type ‘MetaBag -> Product' a1’
with ‘Product' (QueryBuilder ProjectProduct)’
Expected type: Parser Product
Actual type: Parser (MetaBag -> Product' a1)
• In the expression:
Product def <$> r .: "title" <*> r .: "price" <*> r .: "category"
<*> pure def
In an equation for ‘parseNamedRecord’:
parseNamedRecord r
= Product def <$> r .: "title" <*> r .: "price" <*> r .: "category"
<*> pure def
In the instance declaration for ‘FromNamedRecord Product’
|
12 | parseNamedRecord r = Product def <$> r .: "title" <*> r .: "price" <*> r .: "category" <*> pure def
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[已解决,感谢@mpscholten 的帮助]
#!/usr/bin/env run-script
module Application.Script.DataLoader where
import Application.Script.Prelude hiding (decode, pack, (.:))
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import Data.Text (pack)
import qualified Data.Vector as V
import Control.Monad (mzero)
parseProduct :: NamedRecord -> Parser Product
parseProduct r = do
title <- r .: "title"
price <- r .: "price"
category <- r .: "category"
newRecord @Product
|> set #title title
|> set #price price
|> set #category category
|> pure
run :: Script
run = do
csvData <- BL.readFile "data/Boiler-en-kookkraan_Boiler.csv"
case decodeByNameWithP parseProduct defaultDecodeOptions csvData of
Left err -> putStrLn $ pack err
Right (_, v) -> V.forM_ v $ \ p ->
putStrLn $ (get #title p) ++ ", " ++ show (get #price p) ++ " euro"
您能分享一下您遇到的错误吗?您需要的产品类型应该在 Generated.Types
中,哪个 intern 由 Application.Script.Prelude
.
加载
我认为您可能有两个模型都具有字段标题。 haskell 中的字段是函数,它们不能被使用两次。
在 FromNamedRecord
实例中,您缺少两个字段:id
和 meta
。 id
字段是记录的第一个字段。 meta
字段是 IHP 用于跟踪验证错误的隐藏字段。它始终是记录的最后一个字段。
解决这个问题的最简单方法是使用 newRecord
并以更明确的方式写出代码:
instance FromNamedRecord Product where
parseNamedRecord r = do
title <- r .: "title"
price <- r .: "price"
category <- r .: "category"
newRecord @Product
|> set #title title
|> set #price price
|> set #category category
|> pure
对于错误“出现歧义‘标题’”,尝试使用 get
函数而不是使用正常的 haskell 访问器函数:
putStrLn $ (get #title p) ++ ", " ++ show (get #price p) ++ " euro"
我使用 IHP(haskell 网络框架)创建了一个网络应用程序。现在我想创建一个 IHP 脚本来将一些外部数据加载到我的数据库中。然而,我从 Prelude 中得到了很多导入冲突,但不是我期望的类型。
#!/usr/bin/env run-script
module Application.Script.DataLoader where
import Application.Script.Prelude hiding (decode, pack, (.:))
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import Data.Text (pack)
import qualified Data.Vector as V
import Control.Monad (mzero)
instance FromNamedRecord Product where
parseNamedRecord r = Product def <$> r .: "title" <*> r .: "price" <*> r .: "category" <*> pure def
run :: Script
run = do
csvData <- BL.readFile "~/tender/data/Boiler-en-kookkraan_Boiler.csv"
case decodeByName csvData of
Left err -> putStrLn $ pack err
Right (_, v) -> V.forM_ v $ \ p ->
putStrLn $ (get #title p) ++ ", " ++ show (get #price p) ++ " euro"
我的 Product
架构如下所示:
CREATE TABLE products (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
title TEXT NOT NULL,
price DOUBLE PRECISION NOT NULL,
category TEXT NOT NULL
);
有没有一种方法可以将我创建的类型用作数据对象,例如读取我的 csv 到?
[更新输出]
Application/Script/DataLoader.hs:12:26: error:
• Couldn't match type ‘MetaBag -> Product' a1’
with ‘Product' (QueryBuilder ProjectProduct)’
Expected type: Parser Product
Actual type: Parser (MetaBag -> Product' a1)
• In the expression:
Product def <$> r .: "title" <*> r .: "price" <*> r .: "category"
<*> pure def
In an equation for ‘parseNamedRecord’:
parseNamedRecord r
= Product def <$> r .: "title" <*> r .: "price" <*> r .: "category"
<*> pure def
In the instance declaration for ‘FromNamedRecord Product’
|
12 | parseNamedRecord r = Product def <$> r .: "title" <*> r .: "price" <*> r .: "category" <*> pure def
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[已解决,感谢@mpscholten 的帮助]
#!/usr/bin/env run-script
module Application.Script.DataLoader where
import Application.Script.Prelude hiding (decode, pack, (.:))
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import Data.Text (pack)
import qualified Data.Vector as V
import Control.Monad (mzero)
parseProduct :: NamedRecord -> Parser Product
parseProduct r = do
title <- r .: "title"
price <- r .: "price"
category <- r .: "category"
newRecord @Product
|> set #title title
|> set #price price
|> set #category category
|> pure
run :: Script
run = do
csvData <- BL.readFile "data/Boiler-en-kookkraan_Boiler.csv"
case decodeByNameWithP parseProduct defaultDecodeOptions csvData of
Left err -> putStrLn $ pack err
Right (_, v) -> V.forM_ v $ \ p ->
putStrLn $ (get #title p) ++ ", " ++ show (get #price p) ++ " euro"
您能分享一下您遇到的错误吗?您需要的产品类型应该在 Generated.Types
中,哪个 intern 由 Application.Script.Prelude
.
我认为您可能有两个模型都具有字段标题。 haskell 中的字段是函数,它们不能被使用两次。
在 FromNamedRecord
实例中,您缺少两个字段:id
和 meta
。 id
字段是记录的第一个字段。 meta
字段是 IHP 用于跟踪验证错误的隐藏字段。它始终是记录的最后一个字段。
解决这个问题的最简单方法是使用 newRecord
并以更明确的方式写出代码:
instance FromNamedRecord Product where
parseNamedRecord r = do
title <- r .: "title"
price <- r .: "price"
category <- r .: "category"
newRecord @Product
|> set #title title
|> set #price price
|> set #category category
|> pure
对于错误“出现歧义‘标题’”,尝试使用 get
函数而不是使用正常的 haskell 访问器函数:
putStrLn $ (get #title p) ++ ", " ++ show (get #price p) ++ " euro"