我试图为我的数据创建一个不具有多态性的实例:
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.FromRow
data MyData = A | B | C
instance FromRow MyData where
fromRow = MyData <$> field -- doesn't compile
但它没有编译。
更新:
我无法编译
instance FromField MyData where
fromField f mbs =
case mbs of
Just val -> A --????
Nothing -> returnError ConversionFailed f "error"
这会引发错误Couldn't match expected type ‘Conversion MyData with actual type MyData
如何让它返回Conversion MyData
?
答案 0 :(得分:2)
你需要提出
fromRow :: RowParser MyData
你有
field :: FromField a => RowParser a
为任何RowParser
实例生成FromField
(行的解析器的片段)。
你可以写
fromRow = field
将单字段行解析为MyData
。但是,您的MyData
类型看起来并不像应该有FromRow
个实例。它可能应该(仅)FromField
实例。
您当前代码的最大技术问题是您尝试将类型构造函数映射到某些内容上。您只能映射 functions (包括数据构造函数和记录字段访问器)。
你可能想要
instance FromField MyData where
fromField f mbs = do
char <- fromField f mbs
case char of
'A' -> pure A
'B' -> pure B
'C' -> pure C
_ -> returnError ConversionFailed f [char]
如果您尝试将包含字符的字段的内容转换为您的类型,则此功能应该有效。如果您正在处理不同类型的字段格式,则可能需要进行调整。
这是使用解析器组合子库的一种非常常见的方法。您应该首先查看库是否为类似类型或类型的组件提供解析器,而不是从头开始为您的类型构建解析器。然后,您可以使用标准Functor
,Applicative
和Monad
操作以及库提供的任何特殊操作来构建解析器。