From 3d23f6c2597b0fcf46e217db4494826078972bf3 Mon Sep 17 00:00:00 2001
From: Viktor Kuncak <viktor.kuncak@epfl.ch>
Date: Thu, 23 Apr 2015 22:22:50 +0200
Subject: [PATCH] Exception monad according to vkuncak

---
 .../higher-order/valid/MonadsException.scala  | 62 +++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 testcases/verification/higher-order/valid/MonadsException.scala

diff --git a/testcases/verification/higher-order/valid/MonadsException.scala b/testcases/verification/higher-order/valid/MonadsException.scala
new file mode 100644
index 000000000..2c8033243
--- /dev/null
+++ b/testcases/verification/higher-order/valid/MonadsException.scala
@@ -0,0 +1,62 @@
+import leon.lang._
+import leon.lang.string._
+
+object TryMonad {
+  
+  // Exception monad similar to Option monad, with a message for None
+  
+  sealed abstract class M[T] {
+    def bind[S](f: T => M[S]): M[S] = {
+      this match {
+        case Exc(str) => Exc[S](str)
+        case Success(t) => f(t)
+      }
+    }
+  }
+  case class Exc[T](err: BigInt) extends M[T]
+  case class Success[T](t: T) extends M[T]
+
+  // unit is success
+  def unit[T](t:T) = Success(t)
+  
+  // all laws hold 
+  def leftIdentity[T,S](t: T, f: T => M[S]): Boolean = {
+    unit(t).bind(f) == f(t)
+  }.holds
+  
+  def rightIdentity[T](m: M[T]): Boolean = {
+    m.bind(unit(_)) == m
+  }.holds
+
+  def associativity[T,S,R](m: M[T], f: T => M[S], g: S => M[R]): Boolean = {
+    m.bind(f).bind(g) == m.bind((t:T) => f(t).bind(g))
+  }.holds
+  
+  // here is how we can use it
+  
+  def plus(x: M[BigInt], y: M[BigInt]) = {
+    x.bind(xv => y.bind(yv => unit(xv+yv)))
+  }
+  
+  def minus(x: M[BigInt], y: M[BigInt]) = {
+    x.bind(xv => y.bind(yv => unit(xv - yv)))
+  }
+  
+  def mul(x: M[BigInt], y: M[BigInt]): M[BigInt] = {
+    x.bind(xv => 
+      if (xv==0) x
+      else y.bind(yv => unit(xv * yv)))
+  }
+  
+  def mydiv(x: M[BigInt], y: M[BigInt]) = {
+    x.bind(xv => y.bind(yv => 
+      if (yv==0) Exc[BigInt](1001)
+      else unit(xv/yv)))
+  }
+  
+  
+  def test1 = plus(unit(10), unit(32))
+  def test2 = plus(mydiv(unit(10), unit(0)), unit(32))
+  def test3 = plus(unit(3), plus(mydiv(unit(10), minus(unit(7), unit(7))), unit(32)))
+  def test4 = mul(unit(0), test3)
+}
-- 
GitLab