Skip to content

Commit

Permalink
move Func,Poly,ToRef,IntoReverse into new mod traits
Browse files Browse the repository at this point in the history
  • Loading branch information
ExpHP committed Apr 10, 2018
1 parent 2532947 commit b73f022
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 74 deletions.
3 changes: 2 additions & 1 deletion core/src/coproduct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@
//! # }
//! ```
use hlist::*;
use hlist::{HNil, HCons};
use indices::{Here, There};
use traits::{Poly, Func, ToRef};

/// Enum type representing a Coproduct. Think of this as a Result, but capable
/// of supporting any arbitrary number of types instead of just 2.
Expand Down
68 changes: 1 addition & 67 deletions core/src/hlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
//! ```
use indices::{Here, There, Suffixed};
use traits::{Poly, Func, ToRef, IntoReverse};

use std::ops::Add;

Expand Down Expand Up @@ -813,21 +814,6 @@ where
}
}

/// Trait that allows for reversing a given data structure.
///
/// Implemented for HLists.
///
/// This functionality is also provided as an [inherent method].
/// However, you may find this trait useful in generic contexts.
///
/// [inherent method]: struct.HCons.html#method.into_reverse
pub trait IntoReverse {
type Output;

/// Reverses a given data structure.
fn into_reverse(self) -> Self::Output;
}

impl IntoReverse for HNil {
type Output = HNil;
fn into_reverse(self) -> Self::Output {
Expand All @@ -850,35 +836,6 @@ where
}
}

/// Wrapper type around a function for polymorphic maps and folds.
///
/// This is a thin generic wrapper type that is used to differentiate
/// between single-typed generic closures `F` that implements, say, `Fn(i8) -> bool`,
/// and a Poly-typed `F` that implements multiple Function types, say
/// `Func<i8, Output=bool>`, `Func<bool, Output=f32>` etc.
///
/// This is needed because there are completely generic impls for many of the
/// HList traits that take a simple unwrapped closure.
#[derive(Debug, Copy, Clone, Default)]
pub struct Poly<T>(pub T);

/// This is a simple, user-implementable alternative to `Fn`.
///
/// Might not be necessary if/when Fn(Once, Mut) traits are implementable
/// in stable Rust
pub trait Func<Input> {
type Output;

/// Call the `Func`.
///
/// Notice that this does not take a self argument, which in turn means `Func`
/// cannot effectively close over a context. This decision trades power for convenience;
/// a three-trait `Fn` heirarchy like that in std provides a great deal of power in a
/// small fraction of use-cases, but it also comes at great expanse to the other 95% of
/// use cases.
fn call(i: Input) -> Self::Output;
}

impl<P, H, Tail> HMappable<Poly<P>> for HCons<H, Tail>
where
P: Func<H>,
Expand Down Expand Up @@ -1018,29 +975,6 @@ where
}
}

/// An alternative to AsRef that does not force the reference type to be a pointer itself.
///
/// This lets us create implementations for our recursive traits that take the resulting
/// Output reference type, without having to deal with strange, spurious overflows
/// that sometimes occur when trying to implement a trait for &'a T (see this comment:
/// https://github.com/lloydmeta/frunk/pull/106#issuecomment-377927198)
///
/// This is essentially From, but the more specific nature of it means it's more ergonomic
/// in actual usage.
///
/// Implemented for HLists.
///
/// This functionality is also provided as an [inherent method].
/// However, you may find this trait useful in generic contexts.
///
/// [inherent method]: struct.HCons.html#method.to_ref
pub trait ToRef<'a> {
type Output;

#[inline(always)]
fn to_ref(&'a self) -> Self::Output;
}

impl<'a> ToRef<'a> for HNil {
type Output = HNil;

Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub mod coproduct;
pub mod generic;
pub mod labelled;
pub mod indices;
pub mod traits;
mod tuples;

#[cfg(test)]
Expand Down
6 changes: 3 additions & 3 deletions core/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,20 +278,20 @@ macro_rules! poly_fn {
(p~ $([$($pars: tt, )*] |$p_args: ident : $p_arg_typ: ty| -> $p_ret_typ: ty { $p_body: expr }, )* ~p f~ $(|$args: ident : $arg_typ: ty| -> $ret_typ: ty { $body: expr }, )* ~f) => {{
struct F;
$(
impl<$($pars,)*> $crate::hlist::Func<$p_arg_typ> for F {
impl<$($pars,)*> $crate::traits::Func<$p_arg_typ> for F {
type Output = $p_ret_typ;

fn call($p_args: $p_arg_typ) -> Self::Output { $p_body }
}
)*
$(
impl $crate::hlist::Func<$arg_typ> for F {
impl $crate::traits::Func<$arg_typ> for F {
type Output = $ret_typ;

fn call($args: $arg_typ) -> Self::Output { $body }
}
)*
$crate::hlist::Poly(F)
$crate::traits::Poly(F)
}}
}

Expand Down
67 changes: 67 additions & 0 deletions core/src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Traits that provide generic functionality for multiple types in frunk
/// An alternative to AsRef that does not force the reference type to be a pointer itself.
///
/// This lets us create implementations for our recursive traits that take the resulting
/// Output reference type, without having to deal with strange, spurious overflows
/// that sometimes occur when trying to implement a trait for &'a T (see this comment:
/// https://github.com/lloydmeta/frunk/pull/106#issuecomment-377927198)
///
/// This is essentially From, but the more specific nature of it means it's more ergonomic
/// in actual usage.
///
/// Implemented for HLists.
///
/// This functionality is also provided as an [inherent method].
/// However, you may find this trait useful in generic contexts.
///
/// [inherent method]: struct.HCons.html#method.to_ref
pub trait ToRef<'a> {
type Output;

fn to_ref(&'a self) -> Self::Output;
}

/// Trait that allows for reversing a given data structure.
///
/// Implemented for HLists.
///
/// This functionality is also provided as an [inherent method].
/// However, you may find this trait useful in generic contexts.
///
/// [inherent method]: struct.HCons.html#method.into_reverse
pub trait IntoReverse {
type Output;

/// Reverses a given data structure.
fn into_reverse(self) -> Self::Output;
}

/// Wrapper type around a function for polymorphic maps and folds.
///
/// This is a thin generic wrapper type that is used to differentiate
/// between single-typed generic closures `F` that implements, say, `Fn(i8) -> bool`,
/// and a Poly-typed `F` that implements multiple Function types, say
/// `Func<i8, Output=bool>`, `Func<bool, Output=f32>` etc.
///
/// This is needed because there are completely generic impls for many of the
/// HList traits that take a simple unwrapped closure.
#[derive(Debug, Copy, Clone, Default)]
pub struct Poly<T>(pub T);

/// This is a simple, user-implementable alternative to `Fn`.
///
/// Might not be necessary if/when Fn(Once, Mut) traits are implementable
/// in stable Rust
pub trait Func<Input> {
type Output;

/// Call the `Func`.
///
/// Notice that this does not take a self argument, which in turn means `Func`
/// cannot effectively close over a context. This decision trades power for convenience;
/// a three-trait `Fn` heirarchy like that in std provides a great deal of power in a
/// small fraction of use-cases, but it also comes at great expanse to the other 95% of
/// use cases.
fn call(i: Input) -> Self::Output;
}
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ pub use hlist::HCons;
#[doc(no_inline)]
pub use hlist::lift_from;
#[doc(no_inline)]
pub use hlist::Poly;
pub use traits::Poly;
#[doc(no_inline)]
pub use hlist::Func;
pub use traits::Func;
#[doc(no_inline)]
pub use hlist::ToRef; // useful for where bounds
pub use traits::ToRef; // useful for where bounds

#[doc(no_inline)]
pub use coproduct::Coproduct;
Expand Down

0 comments on commit b73f022

Please sign in to comment.