https://discourse.purescript.org/t/lazy-loading-routes-in-tea-style-app/141/2
- Here, we aren't first-class modules, because we are still using the normal module definition and import system. We believe that first-class modules refer to a special feature in OCaml.
- Can not refer to type classes across a lazy-load boundary. Type-class instances and classes are not first-class values.
- Presume the lazy-loaded module is bundled/includes its own dependencies. This resolves diamond dependency problem.
- Backend can choose to ignore the lazy loading (e.g. Erlang). It simply enables a programmer to declare a dynamic loading boundary which they have prepared.
module Lazy exports (trans) where
import LazyTransitive (trans :: String)
data LazyType = LazyType String
class LazyLoad where
load :: { val1 :: LazyLoad => String }
val1 :: String
val1 = “lazy loaded ” <> (getA :: TypeA)
val2 :: LazyType
val2 = LazyType “there”
module Main where
type Lazy = { val1 :: String, LazyType :: String -> LazyType }
main = do
— LazyLoad is available before lazyLoading the module.
mod <- (lazyLoad :: Lazy)
let x :: LazyType
x = LazyType “here”
let y :: LazyLoad
y = mod.val2 :: LazyLoad
module Main where
lazy import Lazy as Lazy
-- Lazy :: LazyModule { val1 :: String, LazyType :: String -> LazyType }
-- type LazyModule a = OPAQUE -- Provided by Prim.
—- Eject LazyModule:
-- lazyLoadEff :: forall a. LazyModule a -> Eff a
-- e.g.
-- foreign import lazyLoadAff
-- exports.lazyLoadAff = function(moduleName, succCb, errCb) {
-- import(moduleName).then(succCb).catch(errCb); -- Use ECMAScript Dynamic Import syntax or alternative.
-- };
-- lazyLoadEff :: forall a. LazyModule a -> Eff a
-- exports.lazyLoadEff = function(moduleName, succCb, errCb) {
-- return require(moduleName); -- Use NodeJS require syntax.
-- };
main = do
-- LazyType *type* is available before lazyLoading the module.
mod :: Lazy <- (lazyLoadEff Lazy)
let x :: LazyType
x = LazyType “here”
let y :: LazyLoad
y = mod.val2 :: LazyLoad
module Main where
lazy import Lazy as Lazy
— Lazy.module :: LazyModule { val1 :: String, LazyType :: String -> LazyType }
main = do
— LazyLoad *type* is available before lazyLoading the module.
mod <- (lazyLoad Lazy.module)
let x :: LazyType
x = LazyType “here”
let y :: LazyLoad
y = mod.val2 :: LazyLoad
let z :: String
z = mod.val1
module Main where
lazy import Lazy as Lazy — refers to C
lazy import Lazy2 as Lazy2 — refers to C
— Duplicate definitions of C exist across in each of these two lazy-loaded modules.
module Lazy where
class LazyLoad where
load :: { val1 :: LazyLoad => String }
val1 :: LazyLoad => String
val1 = “lazy loaded ” <> (getA :: TypeA)
module Lazy where
class HasA where
getA :: String
data TypeA
instance HasA TypeA where
getA = “typeclass instance”
val1 :: String
val1 = “lazy loaded ” <> (getA :: TypeA)
module Main where
Import Lazy (val1, getA, TypeA)
t = true
main =
let x = if t then “here” else val1
-- let y = if t then (“here” <> (getA :: TypeA)) else val1
in log x