gpt4 book ai didi

haskell - 如何为自定义新类型派生 PersistField?

转载 作者:行者123 更新时间:2023-12-02 03:36:08 25 4
gpt4 key购买 nike

这是一个特定于 Yesod 的问题,但即使不知道 Yesod 你也可以帮助我,它与新类型有关。

假设我的配置/模型中有以下简化模型

Value
userId UserId
weight Weight
deriving (Show)

我将在我的 webapp 中同时使用千克和磅,但我决定数据库应该以千克为单位存储东西。为了让类型系统避免混淆这两者,我定义了以下内容:

newtype Weight = Kilograms Int
deriving (Read, Show, Eq, PersistField, PersistFieldSql)

编译得很好,但我如何从表单中使用它?

logForm :: UserId -> Form Value
logForm uid = renderDivs $ Value <$>
pure uid <*>
areq intField "Weight" Nothing

我得到了错误

No instance for (Integral ModelTypes.Weight)
arising from a use of `intField'

我尝试推导 Integral 但随后它提示我没有 Real Weight。不断地,我最终得到:

newtype Weight = Grams Int
deriving (Read, Show, Eq, Enum, Ord, Num, Integral, Real, PersistField, PersistFieldSql)

这是正确的做法吗?好像重复了很多。什么是更好的方法?

一般来说,如果我在 Haskell 中有一个

newtype N = T a

对于具体类型a,我如何让N重新派生a实例中的所有内容,并获得N 派生一些其他类型类(在我的示例中 PersistFieldPersistFieldSql)。非常感谢。

最佳答案

PersistField 与 Field 不同。您想通过导入 Yesod.Forms 来创建自定义字段。这是一个 MathJax 类型的例子 ;)

newtype MathJax = MathJax { unMathJax :: Markdown }
deriving (Eq, Ord, Show, Read, PersistField, PersistFieldSql, IsString, Monoid)

unMM :: MathJax -> Text
unMM = unMarkdown . unMathJax

mathJaxField :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m MathJax
mathJaxField = Field
{ fieldParse = parseHelper $ Right . MathJax . Markdown . Text.filter (/= '\r')
, fieldView = \theId name attrs val _isReq -> toWidget
[hamlet|$newline never
<textarea id="#{theId}" name="#{name}" *{attrs}>#{either id unMM val}
|]
, fieldEnctype = UrlEncoded
}

关于haskell - 如何为自定义新类型派生 PersistField?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23328586/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com