When I move UiRoutes module into a separate file it gives me an error when compiling. This is the first time using Saturn and Giraffe so I'm not sure what is happening? What is the difference having the module in a separate file?
The error I get is: "Value restriction. The value 'uiRouter' has been inferred to have generic type\n val uiRouter : (HttpFunc -> '_a -> HttpFuncResult) when '_a :> AspNetCore.Http.HttpContext \nEither make the arguments to 'uiRouter' explicit or, if you do not intend for it to be generic, add a type annotation."
Program.fs
open Saturn
// MongoDB.FSharp.Serializers.Register()
module ApiRoutes =
open Giraffe
let apiRoutes =
router {
//Routers in here
}
module UiRoutes =
open Giraffe
open Giraffe.ViewEngine
open DBApi
let carsView =
html [] [
//Some HTML
]
let uiRouter = htmlView carsView //HttpFunc -> AspNetCore.Http.HttpContext -> HttpFuncResult
let appRouter =
router {
forward "/api" ApiRoutes.apiRoutes
forward "" UiRoutes.uiRouter
}
let myApp = application { use_router appRouter }
run myApp
Solution:
//Changed
let uiRouter = htmlView carsView
//to:
let (uiRouter: HttpFunc -> Microsoft.AspNetCore.Http.HttpContext -> HttpFuncResult) = htmlView carsView
F# compiles each file separately. When you move the definition of uiRouter
into a different file from the one where it's used, the F# compiler can no longer infer that it has a non-generic type. In other words, when compiling UiRoutes.fs
, the compiler can't tell that you want uiRouter
to have the exact type HttpFunc -> AspNetCore.Http.HttpContext -> HttpFuncResult
. Since F# doesn't allow uiRouter
to have a generic value, you get the value restriction error.
Here are two ways to avoid this situation:
uiRouter
is constrained to a non-generic type by a subsequent use of the value in the same file where it is defined.uiRouter
.