use crate::choice::Choice;
use crate::profunctor::{HKT2, Profunctor};
pub struct TaggedF;
impl HKT2 for TaggedF {
type P<A, B> = B;
}
impl Profunctor for TaggedF {
fn dimap<A: 'static, B: 'static, C, D>(
_f: impl Fn(C) -> A + 'static,
g: impl Fn(B) -> D + 'static,
pab: B,
) -> D {
g(pab)
}
}
impl Choice for TaggedF {
fn left<A, B, C>(pab: B) -> Result<B, C>
where
A: 'static,
B: 'static,
C: 'static,
{
Ok(pab)
}
fn right<A, B, C>(pab: B) -> Result<C, B>
where
A: 'static,
B: 'static,
C: 'static,
{
Err(pab)
}
}
#[cfg(test)]
mod tests {
use super::*;
use proptest::prelude::*;
#[test]
fn tagged_dimap_ignores_f() {
let result = <TaggedF as Profunctor>::dimap(
|_: &str| 42i32, |b: i32| b * 2, 10i32, );
assert_eq!(result, 20);
}
#[test]
fn tagged_choice_left() {
let result = <TaggedF as Choice>::left::<(), i32, &str>(42);
assert_eq!(result, Ok(42));
}
#[test]
fn tagged_choice_right() {
let result = <TaggedF as Choice>::right::<(), i32, &str>(42);
assert_eq!(result, Err(42));
}
#[test]
fn tagged_phantom_a_verification() {
let _: <TaggedF as HKT2>::P<String, i32> = 42;
let _: <TaggedF as HKT2>::P<Vec<u8>, i32> = 42;
}
proptest! {
#[test]
fn tagged_profunctor_identity(x in any::<i32>()) {
let result = <TaggedF as Profunctor>::dimap(|a: i32| a, |b: i32| b, x);
prop_assert_eq!(result, x);
}
}
}