I am writing a library to access a web service through an API. I defined a simple class to represent an API action
case class ApiAction[A](run: Credentials => Either[Error, A])
and some functions that make web service calls
// Retrieve foo by id def get(id: Long): ApiAction[Foo] = ??? // List all foo's def list: ApiAction[Seq[Foo]] = ??? // Create a new foo def create(name: String): ApiAction[Foo] = ??? // Update foo def update(updated: Foo): ApiAction[Foo] = ??? // Delete foo def delete(id: Long): ApiAction[Unit] = ???
I also made ApiAction monad
implicit val monad = new Monad[ApiAction] { ... }
So that I could do something like
create("My foo").run(c) get(42).map(changeFooSomehow).flatMap(update).run(c) get(42).map(_.id).flatMap(delete).run(c)
Now I have problems testing their monad laws.
val x = 42 val unitX: ApiAction[Int] = Monad[ApiAction].point(x) "ApiAction" should "satisfy identity law" in { Monad[ApiAction].monadLaw.rightIdentity(unitX) should be (true) }
because monadLaw.rightIdentity uses equal
def rightIdentity[A](a: F[A])(implicit FA: Equal[F[A]]): Boolean = FA.equal(bind(a)(point(_: A)), a)
and no Equal[ApiAction] .
[error] could not find implicit value for parameter FA: scalaz.Equal[ApiAction[Int]] [error] Monad[ApiAction].monadLaw.rightIdentity(unitX) should be (true) [error] ^
The problem is that I canโt even imagine how Equal[ApiAction] could be defined. ApiAction is an essential function, and I do not know any relation of equality in functions. Of course, you can compare the results of ApiAction , but this is not the same.
I feel that I am doing something terribly wrong or do not understand something significant. So my questions are:
- Does
ApiAction make ApiAction as a monad? - Did I create
ApiAction ? - How to check your monad laws?
equality scala functional-programming monads scalaz
lambdas
source share