How to specify types for a function where they are not used in function arguments?

I am writing some data access procedures using Persistent. I want my API to be defined in terms of the data types that represent JSON, but on the constant side, my data types are defined by a constant template system.

Given that I have mappings from json to database data types, and vice versa, I thought I should write generic data access procedures.

Everything went fine until I tried to write an insert function:

standardInsert :: forall d . forall j . (PersistEntityBackend d ~ SqlBackend, PersistEntity d, SimpleJsonDataAccessConversion jd) => 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 

( j is a type variable for a JSON data type, d is a type variable for a constant data type).

This function has two type variables, j and d , but only j can be inferred from the arguments.

In other words, if I call standardInsert jsonValue , a variable of type d ambiguous.

I want to call it more like in C ++ - standardInsert<FooJsonType, FooPersistentType>(jsonValue) .

How to tell Haskell that d ? Or am I completely wrong about this?

+6
source share
1 answer

GHC will not be able to output a variable of type d . You need to add it to the signature type itself by adding a dummy argument. The standard trick is to use a proxy server for this dummy argument, which means that the caller does not need to specify the actual value of this type.

You can get Proxy from the tagged package for GHC <7.8 or from base for GHC> = 7.8, but for the purpose of explanation I will explicitly indicate here:

 data Proxy a = Proxy standardInsert :: forall d . forall j . (PersistEntityBackend d ~ SqlBackend, PersistEntity d, SimpleJsonDataAccessConversion jd) => Proxy d -> j -> DatabaseEnvironmentT (Maybe (WithId j)) standardInsert _ json = do (...) 

and then on the call site:

 standardInsert (Proxy :: Proxy FooPersistentType) jsonValue 
+9
source

Source: https://habr.com/ru/post/971994/


All Articles