Project setup
This commit is contained in:
		
						commit
						d59fbba056
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
.bsp/
 | 
			
		||||
.idea/
 | 
			
		||||
target/
 | 
			
		||||
project/target/
 | 
			
		||||
							
								
								
									
										2
									
								
								.scalafmt.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.scalafmt.conf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
version = 2.5.0
 | 
			
		||||
maxColumn = 120
 | 
			
		||||
							
								
								
									
										16
									
								
								build.sbt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								build.sbt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
addCompilerPlugin("org.typelevel" % "kind-projector" % "0.13.0" cross CrossVersion.full)
 | 
			
		||||
 | 
			
		||||
lazy val root = (project in file(".")).
 | 
			
		||||
  settings(
 | 
			
		||||
    inThisBuild(List(
 | 
			
		||||
      organization := "com.example",
 | 
			
		||||
      scalaVersion := "2.12.9"
 | 
			
		||||
    )),
 | 
			
		||||
    name := "scalatest-example",
 | 
			
		||||
    scalacOptions ++= Seq(
 | 
			
		||||
      "-language:implicitConversions",
 | 
			
		||||
      "-language:higherKinds",
 | 
			
		||||
    )
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.9" % Test
 | 
			
		||||
							
								
								
									
										1
									
								
								project/build.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								project/build.properties
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
sbt.version=1.5.5
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/conversions/identity/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/conversions/identity/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package conversions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Implicit conversions for Identity.
 | 
			
		||||
  */
 | 
			
		||||
package object identity {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/conversions/lisplist/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/conversions/lisplist/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package conversions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Implicit conversions for LispList.
 | 
			
		||||
  */
 | 
			
		||||
package object lisplist {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/conversions/schrodinger/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/conversions/schrodinger/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package conversions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Implicit conversions for Schrodinger.
 | 
			
		||||
  */
 | 
			
		||||
package object schrodinger {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/conversions/state/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/conversions/state/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package conversions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Implicit conversions for State.
 | 
			
		||||
  */
 | 
			
		||||
package object state {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/conversions/superposition/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/conversions/superposition/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package conversions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Implicit conversions for Superposition.
 | 
			
		||||
  */
 | 
			
		||||
package object superposition {}
 | 
			
		||||
							
								
								
									
										33
									
								
								src/main/scala/data/LispList.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/main/scala/data/LispList.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
/**
 | 
			
		||||
  * DO NOT MODIFY THIS FILE. All exercises are performed using implicits only.
 | 
			
		||||
  */
 | 
			
		||||
package data
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * A Lisply-named representation of a singly-linked list and an analogue to
 | 
			
		||||
  * Scala's immutable List. This is a special case of any type A where there
 | 
			
		||||
  * exists a nondeterministic selection of its values that must be specially
 | 
			
		||||
  * handled such that the number of values is inconsequential.
 | 
			
		||||
  */
 | 
			
		||||
sealed trait LispList[+A] {
 | 
			
		||||
 | 
			
		||||
  def car: A
 | 
			
		||||
 | 
			
		||||
  def cdr: LispList[A]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
case class Cons[+A](car: A, cdr: LispList[A]) extends LispList[A]
 | 
			
		||||
 | 
			
		||||
case object Nil extends LispList[Nothing] {
 | 
			
		||||
 | 
			
		||||
  def car: Nothing = throw new Exception("LispList with no car!")
 | 
			
		||||
 | 
			
		||||
  def cdr: LispList[Nothing] = throw new Exception("LispList with no cdr!")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object LispList {
 | 
			
		||||
 | 
			
		||||
  def apply[A](items: A*): LispList[A] = items.foldRight(LispList[A]())(Cons[A])
 | 
			
		||||
 | 
			
		||||
  def apply[A](): LispList[A] = Nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								src/main/scala/data/Schrodinger.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/main/scala/data/Schrodinger.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
/**
 | 
			
		||||
  * DO NOT MODIFY THIS FILE. All exercises are performed using implicits only.
 | 
			
		||||
  */
 | 
			
		||||
package data
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Schrodinger is an analogue to Scala's Option and a special case of
 | 
			
		||||
  * Superposition where a cat may or may not exist and the cat must be specially
 | 
			
		||||
  * handled as if it were simultaneously alive or dead.
 | 
			
		||||
  */
 | 
			
		||||
sealed trait Schrodinger[+A] {
 | 
			
		||||
 | 
			
		||||
  def cat: A
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * The cat is here for pets and he is fluffy.
 | 
			
		||||
  */
 | 
			
		||||
case class Alive[+A](cat: A) extends Schrodinger[A]
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * :(
 | 
			
		||||
  */
 | 
			
		||||
case object Dead extends Schrodinger[Nothing] {
 | 
			
		||||
 | 
			
		||||
  def cat: Nothing = throw new Exception("He's dead Jim!")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								src/main/scala/data/Superposition.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/main/scala/data/Superposition.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
/**
 | 
			
		||||
  * DO NOT MODIFY THIS FILE. All exercises are performed using implicits only.
 | 
			
		||||
  */
 | 
			
		||||
package data
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Superposition is an analogue to Scala's Either and a special case of a
 | 
			
		||||
  * Product (any type of A × B) where only A or B exists, but must be treated
 | 
			
		||||
  * specially as though it could be either one but not both.
 | 
			
		||||
  */
 | 
			
		||||
sealed trait Superposition[+A, +B] {
 | 
			
		||||
 | 
			
		||||
  def downside: A
 | 
			
		||||
 | 
			
		||||
  def upside: B
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Implied negative case of the Superposition. This is probably not the one you
 | 
			
		||||
  * want.
 | 
			
		||||
  */
 | 
			
		||||
case class Downside[+A, +B](downside: A) extends Superposition[A, B] {
 | 
			
		||||
 | 
			
		||||
  def upside = throw new Exception("I got the downside!")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Implied positive case of the Superposition. This is usually the one you want.
 | 
			
		||||
  */
 | 
			
		||||
case class Upside[+A, +B](upside: B) extends Superposition[A, B] {
 | 
			
		||||
 | 
			
		||||
  def downside = throw new Exception("I got the upside!")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/main/scala/data/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/main/scala/data/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
/**
 | 
			
		||||
  * DO NOT MODIFY THIS FILE. All exercises are performed using implicits only.
 | 
			
		||||
  */
 | 
			
		||||
package object data {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * A structure for any type S for which a function exists that derives from
 | 
			
		||||
    * S a product of a value of itself and a value of type A. This can model
 | 
			
		||||
    * stateful computation where state S is given to a function which produces
 | 
			
		||||
    * a potentially-changed state and the result of the computation.
 | 
			
		||||
    *
 | 
			
		||||
    * @tparam S The state type
 | 
			
		||||
    * @tparam A The type returned by the operation
 | 
			
		||||
    */
 | 
			
		||||
  type State[S, +A] = S => (S, A)
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * A special case of any type A that is simply itself.
 | 
			
		||||
    */
 | 
			
		||||
  type Identity[+A] = A
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/applicative/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/applicative/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Applicative operations.
 | 
			
		||||
  */
 | 
			
		||||
package object applicative {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/applicativeError/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/applicativeError/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for ApplicativeError operations.
 | 
			
		||||
  */
 | 
			
		||||
package object applicativeError {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/functor/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/functor/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Functor operations.
 | 
			
		||||
  */
 | 
			
		||||
package object functor {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/identity/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/identity/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Identity.
 | 
			
		||||
  */
 | 
			
		||||
package object identity {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/lisplist/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/lisplist/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for LispList.
 | 
			
		||||
  */
 | 
			
		||||
package object lisplist {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/monad/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/monad/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Monad operations.
 | 
			
		||||
  */
 | 
			
		||||
package object monad {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/monadError/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/monadError/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for MonadError operations.
 | 
			
		||||
  */
 | 
			
		||||
package object monadError {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/monoid/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/monoid/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Monoid operations.
 | 
			
		||||
  */
 | 
			
		||||
package object monoid {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/schrodinger/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/schrodinger/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Schrodinger.
 | 
			
		||||
  */
 | 
			
		||||
package object schrodinger {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/semigroup/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/semigroup/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Semigroup operations.
 | 
			
		||||
  */
 | 
			
		||||
package object semigroup {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/state/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/state/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for State.
 | 
			
		||||
  */
 | 
			
		||||
package object state {}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/main/scala/extensions/superposition/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/scala/extensions/superposition/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Extension methods for Superposition.
 | 
			
		||||
  */
 | 
			
		||||
package object superposition {}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/main/scala/instances/identity/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/main/scala/instances/identity/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
package instances
 | 
			
		||||
 | 
			
		||||
import data._
 | 
			
		||||
import typeclasses._
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Typeclass instances for Identity
 | 
			
		||||
  */
 | 
			
		||||
package object identity {
 | 
			
		||||
 | 
			
		||||
  implicit val identityFunctor: Functor[Identity] = ???
 | 
			
		||||
 | 
			
		||||
  implicit val identityApplicative: Applicative[Identity] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def identityApplicativeError[E]: ApplicativeError[Identity, E] = ???
 | 
			
		||||
 | 
			
		||||
  implicit val identityMonad: Monad[Identity] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def identityMonadError[E]: MonadError[Identity, E] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def identitySemigroup[A]: Semigroup[Identity[A]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def identityMonoid[A]: Monoid[Identity[A]] = ???
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								src/main/scala/instances/lisplist/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/main/scala/instances/lisplist/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
package instances
 | 
			
		||||
 | 
			
		||||
import data._
 | 
			
		||||
import typeclasses._
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Typeclass instances for LispList
 | 
			
		||||
  */
 | 
			
		||||
package object lisplist {
 | 
			
		||||
 | 
			
		||||
  implicit val lispListFunctor: Functor[LispList] = ???
 | 
			
		||||
 | 
			
		||||
  implicit val lispListApplicative: Applicative[LispList] = ???
 | 
			
		||||
 | 
			
		||||
  implicit val lispListMonad: Monad[LispList] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def lispListMonoid[A]: Monoid[LispList[A]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def lispListSemigroup[A]: Semigroup[LispList[A]] = ???
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/main/scala/instances/schrodinger/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/scala/instances/schrodinger/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
package instances
 | 
			
		||||
 | 
			
		||||
import data._
 | 
			
		||||
import typeclasses._
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Typeclass instances for Schrodinger
 | 
			
		||||
  */
 | 
			
		||||
package object schrodinger {
 | 
			
		||||
 | 
			
		||||
  implicit val schrodingerFunctor: Functor[Schrodinger[*]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit val schrodingerApplicative: Applicative[Schrodinger[*]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def schrodingerApplicativeError[E]
 | 
			
		||||
      : ApplicativeError[Schrodinger[*], E] = ???
 | 
			
		||||
 | 
			
		||||
  implicit val schrodingerMonad: Monad[Schrodinger[*]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def schrodingerMonadError[E]: MonadError[Schrodinger[*], E] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def schrodingerMonoid[A]: Monoid[Schrodinger[A]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def schrodingerSemigroup[A]: Semigroup[Schrodinger[A]] = ???
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/main/scala/instances/state/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/main/scala/instances/state/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
package instances
 | 
			
		||||
 | 
			
		||||
import data._
 | 
			
		||||
import typeclasses._
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Typeclass instances for State
 | 
			
		||||
  */
 | 
			
		||||
package object state {
 | 
			
		||||
 | 
			
		||||
  implicit def stateFunctor[S]: Functor[State[S, *]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def stateApplicative[S]: Applicative[State[S, *]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def stateApplicativeError[S, E]: ApplicativeError[State[S, *], E] =
 | 
			
		||||
    ???
 | 
			
		||||
 | 
			
		||||
  implicit def stateMonad[S]: Monad[State[S, *]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def stateMonadError[S, A]: MonadError[State[S, *], S] = ???
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/main/scala/instances/superposition/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/main/scala/instances/superposition/package.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
package instances
 | 
			
		||||
 | 
			
		||||
import data._
 | 
			
		||||
import typeclasses._
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Typeclass instances for Superposition
 | 
			
		||||
  */
 | 
			
		||||
package object superposition {
 | 
			
		||||
 | 
			
		||||
  implicit def superpositionFunctor[A]: Functor[Superposition[A, *]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def superpositionApplicative[A]: Applicative[Superposition[A, *]] =
 | 
			
		||||
    ???
 | 
			
		||||
 | 
			
		||||
  implicit def superpositionApplicativeError[A]
 | 
			
		||||
      : ApplicativeError[Superposition[A, *], A] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def superpositionMonad[A]: Monad[Superposition[A, *]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def superpositionMonadError[A]: MonadError[Superposition[A, *], A] =
 | 
			
		||||
    ???
 | 
			
		||||
 | 
			
		||||
  implicit def superpositionMonoid[A, B]: Monoid[Superposition[A, B]] = ???
 | 
			
		||||
 | 
			
		||||
  implicit def superpositionSemigroup[A, B]: Semigroup[Superposition[A, B]] =
 | 
			
		||||
    ???
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/main/scala/typeclasses/Applicative.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/main/scala/typeclasses/Applicative.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
package typeclasses
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Defines the Applicative operations for any type of kind F[_]. Applicative
 | 
			
		||||
  * is a special case of Functor that can apply a function lifted into F[_] to
 | 
			
		||||
  * a value also lifted into F[_].
 | 
			
		||||
  */
 | 
			
		||||
trait Applicative[F[_]] extends Functor[F] {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Lift a value into F[_].
 | 
			
		||||
    */
 | 
			
		||||
  def pure[A](a: A): F[A] = ???
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Lift a value into F[_] and apply it to a lifted function.
 | 
			
		||||
    */
 | 
			
		||||
  def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * This can be defined in terms of ap and pure alone, try it out!
 | 
			
		||||
    */
 | 
			
		||||
  override def map[A, B](fa: F[A])(f: A => B): F[B] = ???
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/main/scala/typeclasses/ApplicativeError.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/scala/typeclasses/ApplicativeError.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
package typeclasses
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Defines the ApplicativeError operations for any type of kind F[_] for error
 | 
			
		||||
  * type E. ApplicativeError is a special case of Applicative where the type
 | 
			
		||||
  * kind of F[_] may represent a superposition of "success" or "error" cases
 | 
			
		||||
  * and affords operations to create and recover these error cases.
 | 
			
		||||
  */
 | 
			
		||||
trait ApplicativeError[F[_], E] extends Applicative[F] {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Lift an error handler into F[_] to apply to E.
 | 
			
		||||
    */
 | 
			
		||||
  def handleError[A](fa: F[A])(f: E => A): F[A]
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Lift an error handler into F[_] to apply to E, returning a lifted result.
 | 
			
		||||
    */
 | 
			
		||||
  def handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A]
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * A special case of pure() which lifts an error E into F[_].
 | 
			
		||||
    */
 | 
			
		||||
  def raiseError[A](e: E): F[A] = ???
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/main/scala/typeclasses/Functor.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/main/scala/typeclasses/Functor.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
package typeclasses
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Defines the Functor operations for any type of kind F[_]. Functors allow for
 | 
			
		||||
  * a function to be applied to a value lifted into F[_].
 | 
			
		||||
  */
 | 
			
		||||
trait Functor[F[_]] {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Applies a lifted value to a function.
 | 
			
		||||
    */
 | 
			
		||||
  def map[A, B](fa: F[A])(f: A => B): F[B]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								src/main/scala/typeclasses/Monad.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/main/scala/typeclasses/Monad.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
package typeclasses
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Defines the Monad operations for any type of kind F[_]. A Monad is a special
 | 
			
		||||
  * case of Applicative where the application of a function to a lifted value
 | 
			
		||||
  * in F[_] may itself return a lifted value. This is especially powerful because
 | 
			
		||||
  * the lifted result may represent a case against which no further operations
 | 
			
		||||
  * may be performed, which can model short-circuiting on errors!
 | 
			
		||||
  */
 | 
			
		||||
trait Monad[F[_]] extends Applicative[F] {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Lift an apply a function into F[_] and apply it to the value. The function
 | 
			
		||||
    * returns its own lifted result.
 | 
			
		||||
    */
 | 
			
		||||
  def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								src/main/scala/typeclasses/MonadError.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/scala/typeclasses/MonadError.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
package typeclasses
 | 
			
		||||
 | 
			
		||||
import data.Superposition
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Defines the MonadOperations operations for any type of kind F[_] for error
 | 
			
		||||
  * type E. MonadError is a special case of ApplicativeError and Monad that
 | 
			
		||||
  * further augments error handling operations.
 | 
			
		||||
  */
 | 
			
		||||
trait MonadError[F[_], E] extends Monad[F] with ApplicativeError[F, E] {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Replaces A with E if the lifted A does not satisfy the predicate.
 | 
			
		||||
    */
 | 
			
		||||
  def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A]
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Replaces A with E by means of A if the lifted A does not satisfy the predicate.
 | 
			
		||||
    */
 | 
			
		||||
  def ensureOr[A](fa: F[A])(error: A => E)(predicate: A => Boolean): F[A]
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Applies a partial function to the E, if any.
 | 
			
		||||
    */
 | 
			
		||||
  def adaptError[A](fa: F[A])(pf: PartialFunction[E, E]): F[A]
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Inverse of ApplicativeError attempt().
 | 
			
		||||
    */
 | 
			
		||||
  def rethrow[A, EE <: E](fa: F[Superposition[EE, A]]): F[A]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								src/main/scala/typeclasses/Monoid.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/main/scala/typeclasses/Monoid.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
package typeclasses
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * A Monoid is a special case of a Semigroup for which an element of A, when
 | 
			
		||||
  * applied to any other element of A in any order, returns that other element.
 | 
			
		||||
  * It forms an identity value with which its application merely returns the
 | 
			
		||||
  * identity of its associated operand, similar in concept to the identity
 | 
			
		||||
  * function.
 | 
			
		||||
  */
 | 
			
		||||
trait Monoid[A] extends Semigroup[A] {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * The identity of A.
 | 
			
		||||
    */
 | 
			
		||||
  def empty: A
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								src/main/scala/typeclasses/Semigroup.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/main/scala/typeclasses/Semigroup.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
package typeclasses
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * A semigroup is a special case of a binary operation that is both associative
 | 
			
		||||
  * and for any two A the operation returns another member of A. In a sense, the
 | 
			
		||||
  * Semigroup operation can be used from any two starting members of A to produce
 | 
			
		||||
  * all successive members of A.
 | 
			
		||||
  */
 | 
			
		||||
trait Semigroup[A] {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    * Binary, associative operation against two of A to produce another A.
 | 
			
		||||
    */
 | 
			
		||||
  def <>(x: A, b: A): A
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								src/test/scala/conversions/LispListSpec.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/test/scala/conversions/LispListSpec.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
package conversions
 | 
			
		||||
 | 
			
		||||
import data.{Cons, Nil}
 | 
			
		||||
import org.scalatest.matchers.should.Matchers
 | 
			
		||||
import org.scalatest.wordspec.AnyWordSpecLike
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayOutputStream
 | 
			
		||||
 | 
			
		||||
class LispListSpec extends AnyWordSpecLike with Matchers {
 | 
			
		||||
 | 
			
		||||
  "LispList" can {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      * Exercise: Implicit Conversions
 | 
			
		||||
      */
 | 
			
		||||
    "convert types" which {
 | 
			
		||||
      val lispList = Cons(1, Cons(2, Cons(3, Nil)))
 | 
			
		||||
      def lengthAsList[A](list: List[A]): Int = list.length
 | 
			
		||||
      def lengthAsSeq[A](seq: Seq[A]): Int = seq.length
 | 
			
		||||
 | 
			
		||||
      "become a List" in {
 | 
			
		||||
        pending
 | 
			
		||||
        //lengthAsList(lispList) should eq(3)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      "become a Seq" in {
 | 
			
		||||
        pending
 | 
			
		||||
        //lengthAsSeq(lispList) should eq(3)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      "throw an exception if getting length as a Seq but actually is a List" in {
 | 
			
		||||
        pending
 | 
			
		||||
        //lengthAsSeq(lispList) should eq(3)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      "become a Seq, but loudly" in {
 | 
			
		||||
        val out = new ByteArrayOutputStream()
 | 
			
		||||
        Console.withOut(out) {
 | 
			
		||||
          pending
 | 
			
		||||
          //lengthAsSeq(lispList) should eq(3)
 | 
			
		||||
        }
 | 
			
		||||
        out.toString should contain("THREE OF THEM!")
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      * Exercise: Explicit conversions with extension methods
 | 
			
		||||
      */
 | 
			
		||||
    "explicitly convert types" which {
 | 
			
		||||
      val lispList = Cons(1, Cons(2, Cons(3, Nil)))
 | 
			
		||||
 | 
			
		||||
      "asList" can {
 | 
			
		||||
        "explicitly become a List" in {
 | 
			
		||||
          pending
 | 
			
		||||
          //lispList.asList should eq(List(1, 2, 3))
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      "asSeq" can {
 | 
			
		||||
        "explicitly become a Seq" in {
 | 
			
		||||
          pending
 | 
			
		||||
          //lispList.asList should eq(Seq(1, 2, 3))
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								src/test/scala/extensions/LispListSpec.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/test/scala/extensions/LispListSpec.scala
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
package extensions
 | 
			
		||||
 | 
			
		||||
import data.{Cons, Nil}
 | 
			
		||||
import org.scalatest.matchers.must.Matchers
 | 
			
		||||
import org.scalatest.wordspec.AnyWordSpecLike
 | 
			
		||||
 | 
			
		||||
class LispListSpec extends AnyWordSpecLike with Matchers {
 | 
			
		||||
 | 
			
		||||
  "LispList" can {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      * Exercise: Create a length method
 | 
			
		||||
      */
 | 
			
		||||
    "length" which {
 | 
			
		||||
      "returns 0 if the list is Nil" in {
 | 
			
		||||
        val lispList = Nil
 | 
			
		||||
        pending
 | 
			
		||||
        //lispList.length should eq(0)
 | 
			
		||||
      }
 | 
			
		||||
      "returns the length of the list" in {
 | 
			
		||||
        val lispList = Cons(1, Cons(2, Cons(3, Nil)))
 | 
			
		||||
        pending
 | 
			
		||||
        //lispList.length should eq(3)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      * Exercise: Create a schrodingersCar method
 | 
			
		||||
      */
 | 
			
		||||
    "schrodingersCar" which {
 | 
			
		||||
      "returns Dead" when {
 | 
			
		||||
        "list is Nil" in {
 | 
			
		||||
          val lispList = Nil
 | 
			
		||||
          pending
 | 
			
		||||
          //lispList.schrodingersCar should eq(Dead)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      "returns Alive containing the first value" when {
 | 
			
		||||
        "the list is not Nil" in {
 | 
			
		||||
          val lispList = Cons("Ferrari", Cons("Lamborghini", Cons("Honda Fit", Nil)))
 | 
			
		||||
          pending
 | 
			
		||||
          //lispList.schrodingersCar should eq(Alive("Ferrari"))
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user