Skip to content

Commit

Permalink
Use curry/uncurry functions
Browse files Browse the repository at this point in the history
  • Loading branch information
d-plaindoux committed Sep 18, 2023
1 parent f767a77 commit 19b8119
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 23 deletions.
21 changes: 15 additions & 6 deletions src/core/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,28 @@
* Copyright (c) 2023 Didier Plaindoux
*/

pub fn uncurry<'a, A, B, C, CURRY>(f: CURRY) -> Box<dyn Fn(A, B) -> C + 'a>
use crate::core::types::FunOnceLT;

pub fn uncurry<'a, A, B, C, F>(f: F) -> Box<dyn Fn(A, B) -> C + 'a>
where
CURRY: Fn(A) -> Box<dyn Fn(B) -> C> + 'a,
F: Fn(A) -> Box<dyn Fn(B) -> C> + 'a,
{
Box::new(move |a, b| f(a)(b))
}

pub fn curry<'a, A, B, C, UNCURRY>(
f: UNCURRY,
) -> Box<dyn FnOnce(A) -> Box<dyn FnOnce(B) -> C + 'a> + 'a>
pub fn curry<'a, A, B, C, F>(f: F) -> FunOnceLT<'a, A, FunOnceLT<'a, B, C>>
where
A: 'a,
UNCURRY: FnOnce(A, B) -> C + 'a,
F: FnOnce(A, B) -> C + 'a,
{
Box::new(move |a| Box::new(move |b| f(a, b)))
}

pub fn curry3<'a, A, B, C, D, F>(f: F) -> FunOnceLT<'a, A, FunOnceLT<'a, B, FunOnceLT<'a, C, D>>>
where
A: 'a,
B: 'a,
F: FnOnce(A, B, C) -> D + 'a,
{
Box::new(move |a| Box::new(move |b| Box::new(move |c| f(a, b, c))))
}
2 changes: 2 additions & 0 deletions src/core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/

pub type Fun<A, B> = Box<dyn Fn(A) -> B>;
pub type Fun2<A, B, C> = Box<dyn Fn(A, B) -> C>;
pub type FunLT<'a, A, B> = Box<dyn Fn(A) -> B + 'a>;
pub type FunOnce<A, B> = Box<dyn FnOnce(A) -> B>;
pub type FunOnceLT<'a, A, B> = Box<dyn FnOnce(A) -> B + 'a>;
pub type FunOnce2LT<'a, A, B, C> = Box<dyn FnOnce(A, B) -> C + 'a>;
41 changes: 25 additions & 16 deletions src/specs/applicative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Copyright (c) 2023 Didier Plaindoux
*/

use crate::core::types::Fun;
use crate::specs::functor::Functor;

pub trait Applicative<'a>: Functor<'a> {
Expand All @@ -15,46 +14,56 @@ pub trait Applicative<'a>: Functor<'a> {
A: Clone,
MAP: Fn(A) -> B;

fn lift1<A, B>(f: Fun<A, B>, ma: Self::T<A>) -> Self::T<B> {
fn lift1<A, B, F>(f: F, ma: Self::T<A>) -> Self::T<B>
where
F: Fn(A) -> B + 'a,
{
Self::map(f, ma)
}

fn lift2<A: Clone, B: Clone, C>(
f: Fun<A, Fun<B, C>>,
ma: Self::T<A>,
mb: Self::T<B>,
) -> Self::T<C> {
fn lift2<A, B, C, F>(f: F, ma: Self::T<A>, mb: Self::T<B>) -> Self::T<C>
where
A: Clone,
B: Clone,
F: Fn(A) -> Box<dyn Fn(B) -> C> + 'a,
{
Self::apply(Self::apply(Self::pure(f), ma), mb)
}
}

pub mod curry {
use crate::core::types::{Fun, FunOnceLT};
use crate::core::functions::{curry, curry3};
use crate::core::types::FunOnceLT;
use crate::specs::applicative::Applicative as Api;

pub trait Applicative<'a>: Api<'a> {
fn apply<A, B, MAP>(mf: Self::T<MAP>) -> FunOnceLT<'a, Self::T<A>, Self::T<B>>
fn apply<A, B, F>(mf: Self::T<F>) -> FunOnceLT<'a, Self::T<A>, Self::T<B>>
where
Self: 'a,
A: Clone,
MAP: Fn(A) -> B,
F: Fn(A) -> B,
{
Box::new(move |ma| <Self as Api<'a>>::apply(mf, ma))
curry(<Self as Api<'a>>::apply)(mf)
}

fn lift1<A, B>(f: Fun<A, B>) -> FunOnceLT<'a, Self::T<A>, Self::T<B>> {
Box::new(move |ma| <Self as Api<'a>>::lift1(f, ma))
fn lift1<A, B, F>(f: F) -> FunOnceLT<'a, Self::T<A>, Self::T<B>>
where
Self: 'a,
F: Fn(A) -> B + 'a,
{
curry(<Self as Api<'a>>::lift1)(f)
}

fn lift2<A, B, C>(
f: Fun<A, Fun<B, C>>,
fn lift2<A, B, C, F>(
f: F,
) -> FunOnceLT<'a, Self::T<A>, FunOnceLT<'a, Self::T<B>, Self::T<C>>>
where
Self: 'a,
A: Clone,
B: Clone,
F: Fn(A) -> Box<dyn Fn(B) -> C> + 'a,
{
Box::new(move |ma| Box::new(move |mb| <Self as Api<'a>>::lift2(f, ma, mb)))
curry3(<Self as Api<'a>>::lift2)(f)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/specs/bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub trait Bind<'a>: Applicative<'a> {
}

pub mod curry {
use crate::core::functions::curry;
use crate::core::types::FunOnceLT;
use crate::specs::bind::Bind as Api;

Expand All @@ -26,7 +27,7 @@ pub mod curry {
Self: 'a,
BIND: Fn(A) -> Self::T<B> + 'a,
{
Box::new(move |f| <Self as Api<'a>>::bind(ma, f))
curry(<Self as Api<'a>>::bind)(ma)
}
}
}
Expand Down

0 comments on commit 19b8119

Please sign in to comment.