Chr*_*ert 5 generics haskell servant
我正在 Servant 中构建一个站点,并且想知道是否无法创建用于生成输入字段的 Generic 实例。
我想要的是有一个
class ToInputField a where
toInputField :: a -> InputField
Run Code Online (Sandbox Code Playgroud)
这样,一个示例实现可以是
instance ToInputField Text where
toInputField t = InputField { type = InputText, value = t, name = "some name which I would like to be derived" }
Run Code Online (Sandbox Code Playgroud)
现在,如果一个类型的每个访问器函数都实现了这个类,我想做一些类似 ToJSON 的事情。
instance ToJSON Person
Run Code Online (Sandbox Code Playgroud)
而是做
class ToForm a where
toForm :: a -> [InputField]
instance ToForm Person
Run Code Online (Sandbox Code Playgroud)
但是有类似的东西toInputField :: Text -> a -> InputField,其中 Text 是访问器字段的名称。所以toInputField可以这样实现
instance ToInputField Text where
toInputField n t = InputField { type = InputText, value = t, name = n }
Run Code Online (Sandbox Code Playgroud)
我有一种感觉,这可以通过泛型实现,但我在创建泛型实现方面的经验为零。此外,我认为应该可以为
class NamedFunctor a where
nfmap :: (Text -> b -> c) -> [c]
Run Code Online (Sandbox Code Playgroud)
其中 Text 是访问器字段的名称。这样我就可以通过简单的方式创建一个表单
data Person = Person { pname :: Text, pheight :: Int } deriving (Generic, NamedFunctor)
toForm :: NamedFunctor a => a -> [InputField]
toForm = nfmap toInputField
Run Code Online (Sandbox Code Playgroud)
这样我就可以用
show . toForm $ User "testName" 172
Run Code Online (Sandbox Code Playgroud)
并得到
"[ InputField { type = InputText, value = "testName", name = "pname" }
, InputField { type = InputNumber, value = "172", name = "pheight" }]"
Run Code Online (Sandbox Code Playgroud)
我问这个更笼统的问题的原因是,我不知道如何实现其中的任何一个,既不是简单的也不是广义的,但我希望已经实现了类似广义的东西,因为这似乎非常有用,并且可用于实现所有类型的事情,其中字段的名称是相关的,就像任何序列化一样。