stu*_*ith 6 haskell type-inference
我正在使用Persistent编写一些数据访问例程.我希望我的API可以用代表JSON的数据类型来定义,但是在持久性方面,我的数据类型是由持久化的模板系统定义的.
鉴于我有从json到数据库数据类型的映射,反之亦然,我认为我应该能够编写通用数据访问例程.
一切顺利,直到我尝试编写插入函数:
standardInsert :: forall d . forall j .
(PersistEntityBackend d ~ SqlBackend, PersistEntity d, SimpleJsonDataAccessConversion j d)
=> j -> DatabaseEnvironmentT (Maybe (WithId j))
standardInsert json = do
maybeId <- runSqlMaybe $ insert db
return $ toApi <$> maybeId
where db = jsonToDataAccess json :: d -- Scoped type variable here.
toApi key = addId key $ dataAccessToJson db
Run Code Online (Sandbox Code Playgroud)
(j
是JSON数据类型d
的类型变量,是持久数据类型的类型变量).
这个函数有两个类型变量,j
和d
,但只j
能够从参数中推断出来.
换句话说,如果我调用standardInsert jsonValue
,则类型变量d
是不明确的.
我想在C++中称它为 - standardInsert<FooJsonType, FooPersistentType>(jsonValue)
.
我如何告诉Haskell是什么d
?或者我是以完全错误的方式解决这个问题?
GHC将无法推断出类型变量d
.您需要通过添加伪参数将其添加到类型签名本身.标准技巧是为此伪参数使用代理,这意味着调用者不需要提供该类型的实际值.
您可以Proxy
从tagged
GHC <7.8或base
GHC> = 7.8 的包中获取,但出于解释的目的,我将在此处明确定义:
data Proxy a = Proxy
standardInsert :: forall d . forall j .
(PersistEntityBackend d ~ SqlBackend,
PersistEntity d, SimpleJsonDataAccessConversion j d)
=> Proxy d -> j -> DatabaseEnvironmentT (Maybe (WithId j))
standardInsert _ json = do (...)
Run Code Online (Sandbox Code Playgroud)
然后在呼叫站点:
standardInsert (Proxy :: Proxy FooPersistentType) jsonValue
Run Code Online (Sandbox Code Playgroud)