[英]Using Generic Deriving with a Record Haskell
I am basically attempting to see if I can emulate an ORM framework within Haskell, so that if a user wants to make a database model, they would do something like this 我基本上试图看看我是否可以在Haskell中模拟一个ORM框架,这样如果用户想要创建一个数据库模型,他们会做这样的事情
data Car = Car {
company :: String,
model :: String,
year :: Int
} deriving (Model)
Where the table would be "Car", and the columns would be the company,model,year 表格为“Car”,列为公司,型号,年份
To do this within Haskell, you have to use a combination of classes and generics, and this is where I am getting stuck. 要在Haskell中执行此操作,您必须使用类和泛型的组合,这就是我遇到困难的地方。 Using this tutorial ( http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/generic-programming.html ), I came up with this (which was just basically copying and renaming so I can get the code working)
使用本教程( http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/generic-programming.html ),我想出了这个(基本上是复制和重命名,所以我可以得到代码工作)
{-# LANGUAGE DeriveGeneric, TypeOperators, TypeSynonymInstances, FlexibleInstances #-}
module Main where
import GHC.Generics
class SModel b where
s_new :: b -> IO()
instance SModel Int where
s_new s = putStrLn s++":Int"
instance SModel Integer where
s_new s = putStrLn s++":Integer"
instance SModel String where
s_new s = putStrLn s++":String"
class Model m where
new :: m a -> IO()
instance Model U1 where
new U1 = putStrLn "unit"
instance (Model a, Model b) => Model (a :*: b) where
new (a :*: b) = do
new a
new b
instance (Model a, Model b) => Model (a :+: b) where
new (L1 x) = new x
new (R1 x) = new x
instance (Model a) => Model (M1 i c a) where
new (M1 x) = new x
instance (SModel a) => Model (K1 i a) where
new (K1 x) = s_new x
data Car = Car {
company :: String,
model :: String,
year :: Int
} deriving (Model)
The above code will produces the error 上面的代码会产生错误
Cannot derive well-kinded instance of form `Model (Car ...)'
Class `Model' expects an argument of kind `* -> *'
In the data declaration for `Car'
And I am kind of stuck at this point, I believe I have already instantiated all of the required Generic types to cover a record 我有点陷入困境,我相信我已经实例化了所有必需的通用类型来覆盖记录
As kosmikus said in his comment, you cannot derive Model
directly. 正如kosmikus在评论中所说,你无法直接推导出
Model
。 First you need a 'front-end' class for Model
providing a generic default, which could look like this: 首先,你需要一个提供通用默认值的
Model
的“前端”类,它可能如下所示:
class FModel a where
fnew :: a -> IO()
default new :: (Generic a, Model (Rep a)) => a -> IO()
fnew = new . from
Then you can just do: 然后你可以这样做:
Car = ... deriving Generic
instance FModel Car
And you have the desired instance. 而你有所需的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.