Skip to content

Instantly share code, notes, and snippets.

@Woody88
Last active January 11, 2020 17:45
Show Gist options
  • Select an option

  • Save Woody88/a376c1d3dc222bef28e0e977ef8a0e6f to your computer and use it in GitHub Desktop.

Select an option

Save Woody88/a376c1d3dc222bef28e0e977ef8a0e6f to your computer and use it in GitHub Desktop.
No type class instance was found for
Network.Wai.Router.Internal.RouteContext (Cons "user"
{ params :: { id :: Int
}
}
Nil
)
( user :: { params :: { id :: Int
}
}
)
( user :: { params :: { id :: t7
| t8
}
| t9
}
-> t10 Unit
)
Effect
The instance head contains unknown type variables. Consider adding a type annotation.
while applying a function matchRoutes
of type RowToList t0 t1 => RowToList t2 t3 => Monad t4 => RouteToVariant t1 t2 => RouteContext t3 t2 t5 t4 => t6 t0 -> Record t5 -> String -> t4 Unit
to argument RProxy
while inferring the type of matchRoutes RProxy
in value declaration checkMatchRoutes
where t4 is an unknown type
t5 is an unknown type
t3 is an unknown type
t2 is an unknown type
t1 is an unknown type
t0 is an unknown type
t6 is an unknown type
t7 is an unknown type
t10 is an unknown type
t8 is an unknown type
t9 is an unknown type
module Network.Wai.Router.Internal where
import Prelude
import Control.Monad.Except (ExceptT(..))
import Control.Monad.Reader (class MonadReader, ReaderT(..), ask, runReaderT)
import Control.Monad.ST (run)
import Data.Either (Either(..))
import Data.Symbol (class IsSymbol, SProxy(..))
import Data.Variant (class VariantMatchCases, Variant)
import Data.Variant as Variant
import Effect (Effect)
import Effect.Class.Console as Console
import Effect.Exception (throw)
import Network.HTTP.Types (status200, status500)
import Network.Wai (Application, responseStr)
import Network.Wai.Internal (Request(..), Response)
import Network.Wai.Router.Core (class ParsePath, parsePath)
import Prim.Row as Row
import Prim.RowList as RL
import Record as Record
import Type.Data.Row (RProxy(..))
import Type.Data.RowList (RLProxy(..))
import Type.Proxy (Proxy(..))
foreign import kind RequestMethod
foreign import data GetRequest :: RequestMethod
foreign import data PostRequest :: RequestMethod
foreign import kind MediaType
foreign import data JSON :: MediaType
data Route (path :: Symbol) (method :: RequestMethod) body resp (ctype :: MediaType) (props :: # Type)
type Get url res ctype props = Route url GetRequest Void res ctype props
type Handler ressource r = ExceptT String Effect r
newtype NoMatch = NoMatch String
type GetUser
= Get "/user/{id:Int}" User JSON ()
newtype User = User String
derive newtype instance stringUser :: Show User
checkMatchRoutes :: Effect Unit
checkMatchRoutes = matchRoutes (RProxy :: RProxy (user :: GetUser)) { user: \conn -> Console.logShow conn.params.id } "/user/5"
matchRoutes :: forall proxy routes routesL var varL handlers m
. RL.RowToList routes routesL
=> RL.RowToList var varL
=> Monad m
=> RouteToVariant routesL var
=> RouteContext varL var handlers m
=> proxy routes
-> Record handlers
-> String
-> m Unit
matchRoutes _ handlers path = do
case routesToVariant (RLProxy :: RLProxy routesL) path of
Left l -> pure unit
Right v -> do
routeContext (RLProxy :: RLProxy varL) v handlers -- { user: \conn -> Console.logShow conn.params.id }
class RouteContext (routes :: RL.RowList) (routing :: # Type) (handlers :: # Type) m where
routeContext :: RLProxy routes -> Variant routing -> Record handlers -> m Unit
instance routeContextNil :: (Monad m) => RouteContext RL.Nil routing handlers m where
routeContext _ _ _ = pure unit
instance routeContextCons ::
( Monad m
, IsSymbol name
, Row.Cons name handler t1 handlers
, Row.Cons name route () routers
, RouteContext rtail routers handlers m
) => RouteContext (RL.Cons name (Route path method body res ctype conf) rtail) routers handlers m where
routeContext routersP routers handlers = do
let nameP = SProxy :: SProxy name
(handle :: handler) = Record.get nameP handlers
routeFn = Variant.case_
# Variant.on nameP (\conn -> handle)
_ <- pure $ routeFn routers
routeContext routersP routers handlers
injectParams :: forall name prow r t1
. Row.Cons name { params :: { | prow }} t1 r
=> IsSymbol name
=> SProxy name
-> Record prow
-> Variant r
injectParams name row = Variant.inj name { params: row }
class RouteToVariant
(routes :: RL.RowList)
(var :: # Type)
| routes -> var where
routesToVariant :: RLProxy routes -> String -> Either NoMatch (Variant var)
instance routeToVariantNil :: RouteToVariant RL.Nil () where
routesToVariant _ route = Left (NoMatch route)
instance routeToVariantCons ::
( ParsePath path row
, IsSymbol rName
, RouteToVariant rTail var'
, Row.Cons rName { params :: { | row }} var' var
, Row.Union var' var'' var
) => RouteToVariant (RL.Cons rName (Route path method body res ctype conf) rTail) var where
routesToVariant _ route = case parsePath (SProxy :: SProxy path) route of
Right (r :: { | row }) ->
pure $ injectParams (SProxy :: SProxy rName) r
Left l -> Variant.expand <$> routesToVariant (RLProxy :: RLProxy rTail) route
instance routeToVariantConsSProxy ::
( ParsePath path row
, IsSymbol rName
, RouteToVariant rTail var'
, Row.Cons rName { params :: { | row }} var' var
, Row.Union var' var'' var
) => RouteToVariant (RL.Cons rName (SProxy path) rTail) var where
routesToVariant _ route = case parsePath (SProxy :: SProxy path) route of
Right (r :: { | row }) ->
pure $ injectParams (SProxy :: SProxy rName) r
Left l -> Variant.expand <$> routesToVariant (RLProxy :: RLProxy rTail) route
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment