efold Haskell - - :
efold :: forall n m b.
(forall a. n a)->
(forall a.(m a, n (Pair a)) -> n a)->
(forall a.Pair (m a) -> m (Pair a))->
(forall a.(a -> m b) -> Nest a -> n b)
efold e f g h Nil = e
efold e f g h (Cons (x,xs)) = f (h x, efold e f g (g . pair h) xs
F # , n m " " - , , F # ( .NET).
, . , , , - , , . - :
efold e f g h example ≡
f (h 1, f ((g << pair h) (2, 3), f ((g << pair (g << pair h)) ((4,5), (6,7)), e)))
, h , f
. g h ( h a -> m b Pair a -> m (Pair b) Pair (Pair a) -> m (Pair (Pair b)) ..) f , h f. , e , f.
, , . f, , . g, , (, , , g, fun (a,b) -> b,a).
- efold n, m, . , , Nest, n _ m _ int. , n _ m _ :
let rec efold<'n,'m,'a> (e:'n) (f:'m*'n->'n) (g:Pair<'m> -> 'm) (h:'a->'m) : Nest<'a> -> 'n = function
| Nil -> e
| Cons(x,xs) -> f (h x, efold e f g (g << (pair h)) xs)
let total = efold 0 up up id example
, n m , (, , , F # - ). , , n 'a= list<'a> m 'b= 'b. e , forall 'a.list<'a> [], :
type ListIdF =
abstract Apply : 'a * list<Pair<'a>> -> list<'a>
type ListIdG =
abstract Apply : Pair<'a> -> Pair<'a>
let rec efold<'a,'b> (f:ListIdF) (g:ListIdG) (h:'a -> 'b) : Nest<'a> -> list<'b> = function
| Nil -> []
| Cons(x,xs) -> f.Apply(h x, efold f g (pair h >> g.Apply) xs)
let toList n = efold { new ListIdF with member __.Apply(a,l) = a::(List.collect (fun (x,y) -> [x;y]) l) } { new ListIdG with member __.Apply(p) = p } id n
F # , , . , Higher. .
App<'T,'a>, - T<'a>, , App<_,_>:
type App<'F, 'T>(token : 'F, value : obj) =
do
if obj.ReferenceEquals(token, Unchecked.defaultof<'F>) then
raise <| new System.InvalidOperationException("Invalid token")
member self.Apply(token' : 'F) : obj =
if not (obj.ReferenceEquals(token, token')) then
raise <| new System.InvalidOperationException("Invalid token")
value
, ( ):
type Const<'a> private () =
static let token = Const ()
static member Inj (value : 'a) =
App<Const<'a>, 'b>(token, value)
static member Prj (app : App<Const<'a>, 'b>) : 'a =
app.Apply(token) :?> _
// App<List, 'a> represents list<'a>
type List private () =
static let token = List()
static member Inj (value : 'a list) =
App<List, 'a>(token, value)
static member Prj (app : App<List, 'a>) : 'a list =
app.Apply(token) :?> _
// App<Id, 'a> represents just a plain 'a
type Id private () =
static let token = Id()
static member Inj (value : 'a) =
App<Id, 'a>(token, value)
static member Prj (app : App<Id, 'a>) : 'a =
app.Apply(token) :?> _
// App<Nest, 'a> represents a Nest<'a>
type Nest private () =
static let token = Nest()
static member Inj (value : Nest<'a>) =
App<Nest, 'a>(token, value)
static member Prj (app : App<Nest, 'a>) : Nest<'a> =
app.Apply(token) :?> _
:
type E<'N> =
abstract Apply<'a> : unit -> App<'N,'a>
type F<'M,'N> =
abstract Apply<'a> : App<'M,'a> * App<'N,'a*'a> -> App<'N,'a>
type G<'M> =
abstract Apply<'a> : App<'M,'a> * App<'M,'a> -> App<'M,'a*'a>
:
let rec efold<'N,'M,'a,'b> (e:E<'N>) (f:F<'M,'N>) (g:G<'M>) (h:'a -> App<'M,'b>) : Nest<'a> -> App<'N,'b> = function
| Nil -> e.Apply()
| Cons(x,xs) -> f.Apply(h x, efold e f g (g.Apply << pair h) xs)
efold Inj Prj, , :
let toList n =
efold { new E<_> with member __.Apply() = List.Inj [] }
{ new F<_,_> with member __.Apply(m,n) = Id.Prj m :: (n |> List.Prj |> List.collect (fun (x,y) -> [x;y])) |> List.Inj }
{ new G<_> with member __.Apply(m1,m2) = (Id.Prj m1, Id.Prj m2) |> Id.Inj }
Id.Inj
n
|> List.Prj
let sumElements n =
efold { new E<_> with member __.Apply() = Const.Inj 0 }
{ new F<_,_> with member __.Apply(m,n) = Const.Prj m + Const.Prj n |> Const.Inj }
{ new G<_> with member __.Apply(m1,m2) = Const.Prj m1 + Const.Prj m2 |> Const.Inj }
Const.Inj
n
|> Const.Prj
let reverse n =
efold { new E<_> with member __.Apply() = Nest.Inj Nil }
{ new F<_,_> with member __.Apply(m,n) = Cons(Id.Prj m, Nest.Prj n) |> Nest.Inj }
{ new G<_> with member __.Apply(m1,m2) = (Id.Prj 2, Id.Prj m1) |> Id.Inj }
Id.Inj
n
|> Nest.Prj
, , , , App<_,_>. inline ( ):
let inline (|Prj|) (app:App< ^T, 'a>) = (^T : (static member Prj : App< ^T, 'a> -> 'b) app)
let inline prj (Prj x) = x
let inline inj x = (^T : (static member Inj : 'b -> App< ^T, 'a>) x)
let toList n =
efold { new E<List> with member __.Apply() = inj [] }
{ new F<Id,_> with member __.Apply(Prj m, Prj n) = m :: (n |> List.collect (fun (x,y) -> [x;y])) |> inj }
{ new G<_> with member __.Apply(Prj m1,Prj m2) = (m1, m2) |> inj }
inj
n
|> prj
let sumElements n =
efold { new E<Const<_>> with member __.Apply() = inj 0 }
{ new F<Const<_>,_> with member __.Apply(Prj m, Prj n) = m + n |> inj }
{ new G<_> with member __.Apply(Prj m1,Prj m2) = m1 + m2 |> inj }
inj
n
|> prj
let reverse n =
efold { new E<_> with member __.Apply() = Nest.Inj Nil }
{ new F<Id,_> with member __.Apply(Prj m,Prj n) = Cons(m, n) |> inj }
{ new G<_> with member __.Apply(Prj m1,Prj m2) = (m2, m1) |> inj }
inj
n
|> prj