Skip to content

Instantly share code, notes, and snippets.

@zerokarmaleft
Forked from puffnfresh/Monoid.rs
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zerokarmaleft/bf63dff558b183a58822 to your computer and use it in GitHub Desktop.
Save zerokarmaleft/bf63dff558b183a58822 to your computer and use it in GitHub Desktop.
Semigroups and Monoids
class Semigroup a where
mappend :: a -> a -> a
class Semigroup a => Monoid a where
mempty :: a
mconcat :: [a] -> a
mconcat = foldr mappend mempty
instance Semigroup Int where
mappend x y = x + y
instance Monoid Int where
mempty = 0
instance Semigroup String where
mappend x y = x ++ y
instance Monoid String where
mempty = ""
main :: IO ()
main = do
putStrLn $ show (mappend 1 2) -- 3
putStrLn $ mappend "Hello" " world" -- "Hello world"
putStrLn $ show (mempty :: Int) -- 0
putStrLn $ mempty :: String -- ""
putStrLn $ show (mconcat [1 2 3]) -- 6
putStrLn $ mconcat ["foo", "bar", "baz"] -- "foobarbaz"
enum List<A> {
Nil,
Cons(A, Box<List<A>>)
}
fn map<A,B>(f: |A| -> B, xs: Box<List<A>>) -> List<B> {
match *xs {
Nil => Nil,
Cons(head, box tail) => Cons(f(head), box map(f, box tail))
}
}
fn foldl<A,B>(f: |A,B| -> B, z: B, xs: Box<List<A>>) -> B {
match *xs {
Nil => z,
Cons(head, box tail) => f(head, foldl(f, z, box tail))
}
}
trait Semigroup {
fn mappend(a: Self, b: Self) -> Self;
}
trait Monoid: Semigroup {
fn mempty() -> Self;
fn mconcat(xs: Box<List<Self>>) -> Self {
foldl(Semigroup::mappend, Monoid::mempty(), xs)
}
}
impl Semigroup for int {
fn mappend(a: int, b: int) -> int { a + b }
}
impl Monoid for int {
fn mempty() -> int { 0 }
}
impl Semigroup for Box<String> {
fn mappend(a: Box<String>, b: Box<String>) -> Box<String> {
box a.clone().append(b.as_slice())
}
}
impl Monoid for Box<String> {
fn mempty() -> Box<String> { box "".to_string() }
}
fn main() {
println!("{}", Semigroup::mappend(1, 2)); // 3
println!("{}", Semigroup::mappend(box "Hello".to_string(), box " world".to_string())); // "Hello world"
let int_empty: int = Monoid::mempty();
let str_empty: Box<String> = Monoid::mempty();
println!("{}", int_empty); // 0
println!("{}", str_empty); // ""
let ints: Box<List<int>> = box Cons(1, box Cons(2, box Cons(3, box Nil)));
let strs: Box<List<Box<String>> = box Cons(box "foo".to_string(), box Cons(box "bar".to_string(), box Cons(box "baz".to_string(), box Nil)));
println!("{}", Monoid::mconcat(ints)); // 6
println!("{}", Monoid::mconcat(strs)); // "foobarbaz"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment