0

Noobe question. I have the following base trait (could be an abstract class):

trait EState[S, A] {
  def retrn(a: A): EState[S, A]
  def runState(s: S): (A, S)
}

which I will later extend so:

case class AState[S, A](val f: S => (A, S)) extends EState[S,A] {
  override def retrn(a: A): AState[S, A] = AState({ s: S => (a, s) })
  override def runState(s: S) = f(s)
}

The idea is then to use any instance above like this:

case class StateMonad3[S, A, M[S,A] <: EState[S, A]](m : M[S,A]) {
  def retrn(a: A): EState[S, A] = m.retrn(a)
  def retrni(a: A): StateMonad3[S, A, M] = StateMonad3(m.retrn(a))
}

However I get the following error:

[info] Compiling 1 Scala source to gnosis_server/target/scala-2.10/classes...
[error] gnosis_server/examples/lang/scala/StateMonad.scala:138: type mismatch;
[error]  found   : lang.scala.EState[S,A]
[error]  required: M[S,A]
[error]   def retrni(a: A): StateMonad3[S, A, M] = StateMonad3(m.retrn(a))
                                                                      ^

I assumed that the M[S,A] would be valid for any subclass EState[S,A]. So the constructor should work. But it seems like M and EState are different here. How should this actually be coded?

Additionally, I suspect that that the S and A in the Mand the EState are not the same types. Is this correct or are they bound? If not how should one set this up?

Note: I have searched in the site and found some references to the use of implicits and their use in conversions but could out figure out how to do this. I would like to avoid using such (at least what seems to me to be such) a verbose/complicated solution.

TIA.

2
  • 1
    In StateMonad3(m.retrn(a)), m.retrn( a ) evaluates to an instance of EState[ S, A ] . Your StateMonad3 case class expects an argument of type M[ S, A ] ( which is a less generic type as M[ S, A ] <: EState[ S, A ] ), so it won't expects any EState[ S, A ] which is super class of M[ S, A ] but only M[ S, A ] or anytype SM[ S, A ] such that SM[ S, A ] <: M[ S, A ]. Commented Mar 16, 2015 at 9:46
  • Ok. I think I understand now. So to solve the problem I need only make the constructor accept EState[S,A]. So I can pass it an AState[S,A]. Is their any type-magic I can use to make this work: def retrn(a: A): M[S,A] = m.retrn(a)? Or doesn't this make sense. BTW, can you make the comment an answer so I can give you credit? Commented Mar 16, 2015 at 11:01

1 Answer 1

1

If you take a look at StateMonad3(m.retrn(a)) piece, m.retrn(a) returns EState[S, A] but StateMonad3 apply function needs M[S, A] which is EState[S, A]subclass. Exactly with the same reasoning you cannot pass AnyVal to a function which accepts Int.

One more improvement, the val keyword you used in definition of AState is redundant. case class apply function arguments are val by default and the will be defined as case class fields.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.