-
-
Save ramonsnir/2d00ac8242229c6d5e39 to your computer and use it in GitHub Desktop.
HoM for F# 2.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
signature {{FUNCTOR = | |
type 'a t | |
val map : ('a -> 'b) -> 'a t -> 'b t | |
}} | |
module {{ListFunctor : FUNCTOR = | |
type 'a t = 'a list | |
let map = List.map | |
}} | |
// inline modules are not compiled into actual modules, i.e. they are private to everyone, except functors which use them by argument | |
module {{inline ArrayFunctor : FUNCTOR = | |
type 'a t = 'a [] | |
let map = Array.map | |
}} | |
module OptionFunctor = | |
type 'a t = 'a option | |
let map = Option.map | |
module {{OptionFunctor : FUNCTOR}} | |
// the HoM system will assume from now on that there is a module | |
// named OptionFunctor which matches that signature FUNCTOR. | |
functor {{ComposeFunctorsFn(A : FUNCTOR, B : FUNCTOR) : FUNCTOR = | |
type 'a t = 'a A.t B.t | |
let map f = B.map (A.map f) | |
}} | |
module {{ListOptionFunctor = ComposeFunctorsFn(ListFunctor, OptionFunctor)}} | |
module {{ArrayOptionFunctor = ComposeFunctorsFn(ArrayFunctor, OptionFunctor)}} | |
signature {{MONAD = | |
type 'a t | |
val ``return`` : 'a -> 'a t | |
val bind : ('a -> 'b t) -> 'a t -> 'b t | |
}} | |
module {{ListMonadBase : MONAD = | |
type 'a t = 'a list | |
let ``return`` x = [x] | |
let bind = List.collect | |
}} | |
module {{OptionMonadBase : MONAD = | |
type 'a t = 'a option | |
let ``return`` = Some | |
let bind = Option.bind | |
}} | |
signature {{MONAD_CE = | |
inherit MONAD | |
type CE | |
val ce : CE | |
}} | |
functor {{MonadWithComputationExpressionFn(M : MONAD) : MONAD_CE = | |
type 'a t = 'a M.t | |
let ``return`` = M.``return`` | |
let bind = M.bind | |
type CE internal () = | |
member __.Return x = ``return`` x | |
member __.Bind (x, f) = bind f x | |
let ce = CE() | |
}} | |
module {{ListMonad = MonadWithComputationExpressionFn(ListMonadBase)}} | |
module {{OptionMonad = MonadWithComputationExpressionFn(OptionMonadBase)}} | |
functor {{MonadToFunctorFn(M : MONAD) : FUNCTOR = | |
type 'a t = 'a M.t | |
let map f = M.bind (f >> M.``return``) | |
}} | |
module {{ListFunctor2 = MonadToFunctorFn(ListMonad)}} // yes, MONAD_CE is also MONAD! | |
module {{OptionFunctor2 = MonadToFunctorFn(OptionMonad)}} | |
let threeToTwelve = | |
ListMonad.ce { | |
let! x = [1 .. 10] | |
let! y = [2] | |
return x + y | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
The assembly attributes are used when another F# projects imports this project and would like to reuse the signatures/functors. | |
*) | |
[<assembly: FSharp.HigherOrderModules.Runtime.Signature("FUNCTOR", " type 'a t\r\n val map : ('a -> 'b) -> 'a t -> 'b t\r\n")>] | |
do () | |
// this dummy module is so the signature will be tc'ed even if it isn't used | |
module private ``hom test module 6b4ad128 for FUNCTOR`` = | |
type private 'a t = T of 'a | |
let private map (_ : ('a -> 'b)) : 'a t -> 'b t = unbox null | |
module ListFunctor = | |
type 'a t = 'a list | |
let map : ('a -> 'b) -> 'a t -> 'b t = List.map | |
[<assembly: FSharp.HigherOrderModules.Runtime.InlineModule("ArrayFunctor", "inline ArrayFunctor : FUNCTOR =\r\n type 'a t = 'a []\r\n let map = Array.map\r\n")>] | |
do() | |
module private ``hom test module 55d2daec for ArrayFunctor`` = | |
type private 'a t = 'a [] | |
let private map : ('a -> 'b) -> 'a t -> 'b t = Array.map | |
module OptionFunctor = | |
type 'a t = 'a option | |
let map = Option.map | |
[<assembly: FSharp.HigherOrderModules.Runtime.ModuleSignature("OptionFunctor", "FUNCTOR")>] | |
do () | |
[<assembly: FSharp.HigherOrderModules.Runtime.Functor("ComposeFunctorsFn", "(A : FUNCTOR, B : FUNCTOR) : FUNCTOR =\r\n type 'a t = 'a A.t B.t\r\n let map f = B.map (A.map f)\r\n")>] | |
do () | |
// this dummy module is so the functor will be tc'ed even if it isn't used | |
module private ``hom test module 8e37694b for ComposeFunctorsFn`` = | |
module private A = | |
type 'a t = T of 'a | |
let map (_ : ('a -> 'b)) : 'a t -> 'b t = unbox null | |
module private B = | |
type 'a t = T of 'a | |
let map (_ : ('a -> 'b)) : 'a t -> 'b t = unbox null | |
type private 'a t = 'a A.t B.t | |
let private map (f : 'a -> 'b) : 'a t -> 'b t = B.map (A.map f) | |
module ListOptionFunctor = | |
module A = ListFunctor | |
module B = OptionFunctor | |
type 'a t = 'a A.t B.t | |
let map (f : 'a -> 'b) : 'a t -> 'b t = B.map (A.map f) | |
module ArrayOptionFunctor = | |
module A = | |
type 'a t = 'a [] | |
let map = Array.map | |
module B = OptionFunctor | |
type 'a t = 'a A.t B.t | |
let map (f : 'a -> 'b) : 'a t -> 'b t = B.map (A.map f) | |
[<assembly: FSharp.HigherOrderModules.Runtime.Signature("MONAD", " type 'a t\r\n val ``return`` : 'a -> 'a t\r\n val bind : ('a -> 'b t) -> 'a t -> 'b t\r\n")>] | |
do () | |
module private ``hom test module 6b4fe428 for MONAD`` = | |
type private 'a t = T of 'a | |
let private ``return`` (_ : 'a) : 'a t = unbox null | |
let private bind (_ : ('a -> 'b t)) : 'a t -> 'b t = unbox null | |
module ListMonadBase = | |
type 'a t = 'a list | |
let ``return`` (x : 'a) : 'a t = [x] | |
let bind : ('a -> 'b t) -> 'a t -> 'b t = List.collect | |
module OptionMonadBase = | |
type 'a t = 'a option | |
let ``return`` : 'a -> 'a t = Some | |
let bind : ('a -> 'b t) -> 'a t -> 'b t = Option.bind | |
[<assembly: FSharp.HigherOrderModules.Runtime.Signature("MONAD_CE", " inherit MONAD\r\n type CE\r\n val ce : CE\r\n")>] | |
do () | |
module private ``hom test module 75c6e428 for MONAD_CE`` = | |
type private 'a t = T of 'a | |
let private ``return`` (_ : 'a) : 'a t = unbox null | |
let private bind (_ : ('a -> 'b t)) : 'a t -> 'b t = unbox null | |
type private CE = CE of unit | |
let private ce : CE = CE() | |
[<assembly: FSharp.HigherOrderModules.Runtime.Functor("MonadWithComputationExpressionFn", "(M : MONAD) : MONAD_CE =\r\n type 'a t = 'a M.t\r\n let ``return`` = M.``return``\r\n let bind = M.bind\r\n type CE internal () =\r\n member __.Return x = ``return`` x\r\n member __.Bind (x, f) = bind f x\r\n let ce = CE()\r\n")>] | |
do () | |
// this dummy module is so the functor will be tc'ed even if it isn't used | |
module private ``hom test module 45a458cb for MonadWithComputationExpressionFn`` = | |
module private M = | |
type 'a t = T of 'a | |
let ``return`` (_ : 'a) : 'a t = unbox null | |
let bind (x0 : ('a -> 'b t)) : 'a t -> 'b t = unbox null | |
type private 'a t = 'a M.t | |
let private ``return`` (x0 : 'a) : 'a t = M.``return`` x0 | |
let private bind (x0 : ('a -> 'b t)) : 'a t -> 'b t = M.bind x0 | |
type private CE internal () = | |
member __.Return x = ``return`` x | |
member __.Bind (x, f) = bind f x | |
let private ce : CE = CE() | |
module ListMonad = | |
module M = ListMonadBase | |
type 'a t = 'a M.t | |
let ``return`` : 'a -> 'a t = M.``return`` | |
let bind : ('a -> 'b t) -> 'a t -> 'b t = M.bind | |
type CE internal () = | |
member __.Return x = ``return`` x | |
member __.Bind (x, f) = bind f x | |
let ce : CE = CE() | |
module OptionMonad = | |
module M = OptionMonadBase | |
type 'a t = 'a M.t | |
let ``return`` : 'a -> 'a t = M.``return`` | |
let bind : ('a -> 'b t) -> 'a t -> 'b t = M.bind | |
type CE internal () = | |
member __.Return x = ``return`` x | |
member __.Bind (x, f) = bind f x | |
let ce : CE = CE() | |
[<assembly: FSharp.HigherOrderModules.Runtime.Functor("MonadToFunctorFn", "(M : MONAD) : FUNCTOR =\r\n type 'a t = 'a M.t\r\n let map f = M.bind (f >> M.``return``)\r\n")>] | |
do () | |
module private ``hom test module 456b6a2d for MonadToFunctorFn`` = | |
module private M = | |
type 'a t = T of 'a | |
let ``return`` (_ : 'a) : 'a t = unbox null | |
let bind (_ : ('a -> 'b t)) : 'a t -> 'b t = unbox null | |
type private 'a t = 'a M.t | |
let private map (f : 'a -> 'b) : 'a t -> 'b t = M.bind (f >> M.``return``) | |
module ListFunctor2 = | |
module M = ListMonad | |
type 'a t = 'a M.t | |
let map (f : 'a -> 'b) : 'a t -> 'b t = M.bind (f >> M.``return``) | |
module OptionFunctor2 = | |
module M = OptionMonad | |
type 'a t = 'a M.t | |
let map (f : 'a -> 'b) : 'a t -> 'b t = M.bind (f >> M.``return``) | |
let threeToTwelve = | |
ListMonad.ce { | |
let! x = [1 .. 10] | |
let! y = [2] | |
return x + y | |
} |
In theory it could. One solution is to use type providers as preprocessors (i.e. make an .fshm file with code as in the first file here, then use type providers to read that file and supply the modules).
I noticed that quotations aren't supported. I wonder if there's still time to add support? Care to suggest some of your ideas on this thread?
Late late response... Not so active on GitHub lately. Why aren't quotations supported? I know Type Providers dislike quotations (which is a terrible design flaw), but macros have no such problem.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is really interesting! Have you looked to see if any of this could be used within the type provider infrastructure now that it has evolved some?