Использование общего вывода с записью Haskell
Я в основном пытаюсь увидеть, могу ли я эмулировать структуру ORM в Haskell, так что, если пользователь хочет сделать модель базы данных, они сделают что-то вроде этого
data Car = Car {
company :: String,
model :: String,
year :: Int
} deriving (Model)
где таблица будет "автомобиль", а столбцы будут компанией,моделью, годом
чтобы сделать это в Haskell, вы должны использовать комбинацию классов и дженериков, и вот где я застрял. Используя этот учебник (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)
приведенный выше код выдает ошибку
Cannot derive well-kinded instance of form `Model (Car ...)'
Class `Model' expects an argument of kind `* -> *'
In the data declaration for `Car'
и я вроде как застрял на этом этапе, я считаю, что я уже создал все необходимые общие типы, чтобы покрыть запись
1 ответов
As kosmikus сказал в своем комментарии, вы не можете вывести Model
напрямую. Сначала вам нужен класс "front-end" для Model
предоставление общего значения по умолчанию, которое может выглядеть следующим образом:
class FModel a where
fnew :: a -> IO()
default new :: (Generic a, Model (Rep a)) => a -> IO()
fnew = new . from
затем вы можете просто сделать:
Car = ... deriving Generic
instance FModel Car
и у вас есть нужный экземпляр.