1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! A Writer monad implementation

use crate::monoid::{Monoid};

//---------------------------------------------

#[derive(Clone)]  
pub struct Writer<A, W = String>{ 
  run_writer: (A, W)
  }

#[derive(Clone)]  
pub struct WriterIterator<A> {
  traversed: bool,
  value: A,
}


impl<A: Clone> Iterator for WriterIterator<A> {
   type Item = A;
   
   fn next(&mut self) -> Option<A> {
     if self.traversed {None} 
     else {self.traversed = true;
           Some( self.value.clone())}
   }
}

impl<A: Clone, W> IntoIterator for  Writer<A, W> {
  type Item = A;
  type IntoIter = WriterIterator<A>; 
  
  fn into_iter(self) -> Self::IntoIter {
    
    WriterIterator{
      traversed: false,
      value: self.run_writer.0.clone()
    }
  }
}

impl<A, W: Monoid, F> Writer<(A, F), W> 
    where F: FnOnce(W) -> W {

     fn pass(self) -> Writer<A, W> {
     
        let ((a, f), w) = self.run_writer;
        Writer{ run_writer: (a, f(w))}
     }
}


impl<A, W: Monoid + Clone> Writer<A, W> {

   pub fn bind<B, F>(self, f: F) -> Writer<B,W>
        where 
          F: Fn(A) -> Writer<B,W>,
          Self: Sized,
     {
        let (a, w) = self.run_writer;
        let (a1, mut w1) = f( a).run_writer ;
        Writer{ run_writer: (a1, w.mappend(&mut w1))}
     }

    pub fn pure(x: A) -> Self {
        Writer{ run_writer: (x, W::mempty())}
    }
    
    
    pub fn lift<B>(self, x: B) -> Writer<B, W> {
        Writer{ run_writer: (x, self.run_writer.1)}
    }

    pub fn unwrap_pair(self) -> (A, W) {
        self.run_writer
    }
    
    pub fn unwrap(self) -> A {
        self.run_writer.0
    }
  
    pub fn listen<>(self) -> Writer<(A, W), W> {
        let (a, w) = self.run_writer;
        Writer{ run_writer: ((a, (&w).clone()), w)}
    }

    pub fn listens<T, F: Fn(W) -> T>( self, f: F) -> Writer<(A, T), W> {
        let (a, w) = self.run_writer;
        Writer{ run_writer: ((a, f( (&w).clone())), w)}
    }
    
    pub fn censor<F: Fn(W) -> W>(self, f: F) -> Writer<A, W> {
        let (a, w) = self.run_writer;
        Writer{ run_writer: ((a,f), w)}.pass()
     }
}

pub fn tell<W>(s: W) -> Writer<(), W> {
        Writer{ run_writer: ((), s)}
    }

pub fn tell_str(s: &str) -> Writer<(), String> {
        Writer{ run_writer: ((), String::from( s))}
    }

pub fn tell_array<T: Clone>(v: &[T]) -> Writer<(), Vec<T>> {
        Writer{ run_writer: ((), Vec::from( v))}
    }
    
/// Macro for a [Writer monad](https://wiki.haskell.org/All_About_Monads#The_Writer_monad)
///
/// The logger type (a local *Monoid* instance) can be established by using a `tell_...()` generator
/// or by constraining the type of the macro result.
#[macro_export]
macro_rules! wrdo {
  (pure $e:expr                           ) => [Writer::pure($e)];
  (let $v:ident = $e:expr ; $($rest:tt)*) => [Writer::pure($e).bind( move |$v| { wrdo!($($rest)*)} )];
  (_ <- $monad:expr ; $($rest:tt)* ) => [Writer::bind( ($monad), move |_| { wrdo!($($rest)*)} )];
  ($v:ident <- pure $e:expr ; $($rest:tt)* ) => [Writer::bind( Writer::pure($e), move |$v| { wrdo!($($rest)*)} )];
  ($v:ident <- $monad:expr ; $($rest:tt)* ) => [Writer::bind( ($monad), move |$v| { wrdo!($($rest)*)} )];
  ($monad:expr                            ) => [$monad];
}

// use crate::monad::Monad;

/*

// WriterT fails to parse

pub struct WriterT<A, M: Monad, W = String>{ 
  run_writer_t: M<Item=(A, W)>   // associated type not allowed
  }
*/

/*

// defining it as a monad that will have implementation for elements as pairs (A,W)

pub struct WriterT<M>{ 
  run_writer_t: M,   
  }

impl<M, A, W> for WriterT<M> 
      where 
        M: Monad, 
        M::Item = (A,W) // !! equality constraints not yet supported
   {  
}  
*/