Skip to content

Instantly share code, notes, and snippets.

@sopvop
Last active April 5, 2018 10:07
Show Gist options
  • Save sopvop/1b6bdbf35dc1d5105a061ef295836e15 to your computer and use it in GitHub Desktop.
Save sopvop/1b6bdbf35dc1d5105a061ef295836e15 to your computer and use it in GitHub Desktop.
Works in servant-server, can't make my own instances
{-
src/Servant/API/RPC.hs:74:8-55: error: …
Conflicting family instance declarations:
ServerT (RPC e r) m = m (Either (OpenUnion e) r)
-- Defined at /home/lonokhov/work/stagex-store/stagex-api/src/Servant/API/RPC.hs:74:8
ServerT (RPC e (Headers h r)) m = m (Headers
h (Either (OpenUnion e) r))
-- Defined at /home/lonokhov/work/stagex-store/stagex-api/src/Servant/API/RPC.hs:81:8
-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
data RPC e r
instance {-# OVERLAPPABLE #-} (ToJSON (ErrUnion e), ToJSON r)
=> HasServer (RPC e r) ctx where
type ServerT (RPC e r) m = m (Either (OpenUnion e) r)
hoistServerWithContext _ _ nt = nt
route Proxy _ = methodRouter' $ \x -> (getHeaders x, getResponse x)
instance {-# OVERLAPPING #-} (ToJSON (ErrUnion e), ToJSON r, GetHeaders (Headers h r))
=> HasServer (RPC e (Headers h r)) ctx where
type ServerT (RPC e (Headers h r)) m = m (Headers h (Either (OpenUnion e) r))
hoistServerWithContext _ _ nt = nt
route Proxy _ = methodRouter' ([],)
{- As defined in servant, and it works. using same -Xtensions #-}
instance OVERLAPPABLE_
( AllCTRender ctypes a, ReflectMethod method, KnownNat status
) => HasServer (Verb method status ctypes a) context where
type ServerT (Verb method status ctypes a) m = m a
hoistServerWithContext _ _ nt s = nt s
route Proxy _ = methodRouter ([],) method (Proxy :: Proxy ctypes) status
where method = reflectMethod (Proxy :: Proxy method)
status = toEnum . fromInteger $ natVal (Proxy :: Proxy status)
instance OVERLAPPING_
( AllCTRender ctypes a, ReflectMethod method, KnownNat status
, GetHeaders (Headers h a)
) => HasServer (Verb method status ctypes (Headers h a)) context where
type ServerT (Verb method status ctypes (Headers h a)) m = m (Headers h a)
hoistServerWithContext _ _ nt s = nt s
route Proxy _ = methodRouter (\x -> (getHeaders x, getResponse x)) method (Proxy :: Proxy ctypes) status
where method = reflectMethod (Proxy :: Proxy method)
status = toEnum . fromInteger $ natVal (Proxy :: Proxy status)
{- fixed by moving Either to head -}
instance {-# OVERLAPPABLE #-} (ToJSON (ErrUnion e), ToJSON r)
=> HasServer (RPC e (Either (OpenUnion e) r)) ctx where
type ServerT (RPC e (Either (OpenUnion e) r)) m = m (Either (OpenUnion e) r)
hoistServerWithContext _ _ nt = nt
route Proxy _ = methodRouter' ([],)
instance {-# OVERLAPPING #-}
( ToJSON (ErrUnion e)
, ToJSON r
, GetHeaders (Headers h (Either (OpenUnion e) r)))
=> HasServer (RPC e (Headers h (Either (OpenUnion e) r))) ctx where
type ServerT (RPC e (Headers h (Either (OpenUnion e) r))) m = m (Headers h (Either (OpenUnion e) r))
hoistServerWithContext _ _ nt = nt
route Proxy _ = methodRouter' $ \x -> (getHeaders x, getResponse x)
{- Solution 2 -}
class GetRpcResult r e a | r -> e, r -> a where
getRpcResult :: r -> RpcResult e a
instance GetRpcResult (Either (OpenUnion e) a) e a where
getRpcResult = \case
Right r -> RpcSuccess r
Left e -> RpcError e
instance {-# OVERLAPPABLE #-}
( ToJSON (ErrUnion e)
, ToJSON a
, GetRpcResult r e a)
=> HasServer (RPC e r) ctx where
type ServerT (RPC e r) m = m r
hoistServerWithContext _ _ nt = nt
route Proxy _ = methodRouter'
$ \x -> ([], getRpcResult x :: RpcResult e a)
instance {-# OVERLAPPING #-}
( ToJSON (ErrUnion e)
, ToJSON a
, GetRpcResult r e a
, GetHeaders (Headers h r))
=> HasServer (RPC e (Headers h r)) ctx where
type ServerT (RPC e (Headers h r)) m = m (Headers h r)
hoistServerWithContext _ _ nt = nt
route Proxy _ = methodRouter'
$ \x -> (getHeaders x, getRpcResult (getResponse x) :: RpcResult e a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment