-
-
Save zerokarmaleft/bf63dff558b183a58822 to your computer and use it in GitHub Desktop.
Semigroups and Monoids
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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