Scalaz State monad's modify has the following signature:
def modify[S](f: S => S): State[S, Unit]
This allows the state to be replaced by state of the same type, which does not work well when the state includes a shapeless value such as a Record whose type changes as new fields are added. In that case what we need is:
def modify[S, T](f: S => T): State[T, Unit]
What is a good way to adapt Scalaz's State monad to use shapeless state so that one can use Records as opposed to, say, the dreaded Map[String, Any]?
Example:
case class S[L <: HList](total: Int, scratch: L)
def contrivedAdd[L <: HList](n: Int): State[S[L], Int] =
for {
a <- init
_ <- modify(s => S(s.total + n, ('latestAddend ->> n) :: s.scratch))
r <- get
} yield r.total
Update:
The full code for Travis's answer is here.
State is a type alias for a more generic type IndexedStateT that's specifically designed to represent functions that change the state type as state computations:
type StateT[F[_], S, A] = IndexedStateT[F, S, S, A]
type State[S, A] = StateT[Id, S, A]
While it's not possible to write your modify[S, T] using State, it is possible with IndexedState (which is another type alias for IndexedStateT that fixes the effect type to Id):
import scalaz._, Scalaz._
def transform[S, T](f: S => T): IndexedState[S, T, Unit] =
IndexedState(s => (f(s), ()))
You can even use this in for-comprehensions (which has always seemed a little odd to me, since the monadic type changes between operations, but it works):
val s = for {
a <- init[Int];
_ <- transform[Int, Double](_.toDouble)
_ <- transform[Double, String](_.toString)
r <- get
} yield r * a
And then:
scala> s(5)
res5: scalaz.Id.Id[(String, String)] = (5.0,5.05.05.05.05.0)
In your case you might write something like this:
import shapeless._, shapeless.labelled.{ FieldType, field }
case class S[L <: HList](total: Int, scratch: L)
def addField[K <: Symbol, A, L <: HList](k: Witness.Aux[K], a: A)(
f: Int => Int
): IndexedState[S[L], S[FieldType[K, A] :: L], Unit] =
IndexedState(s => (S(f(s.total), field[K](a) :: s.scratch), ()))
And then:
def contrivedAdd[L <: HList](n: Int) = for {
a <- init[S[L]]
_ <- addField('latestAdded, n)(_ + n)
r <- get
} yield r.total
(This may not be the best way of factoring out the pieces of the update operation, but it shows how the basic idea works.)
It's also worth noting that if you don't care about representing the state transformation as a state computation, you can just use imap on any old State:
init[S[HNil]].imap(s =>
S(1, field[Witness.`'latestAdded`.T](1) :: s.scratch)
)
This doesn't allow you to use these operations compositionally in the same way, but it may be all you need in some situations.
Related
I've the written the following Haskell function which accepts two monadic values and combine them into a single monadic value (it's just to illustrate the degree of genericity (or generic-ness) that Haskell type-system could support).
combine x y = do
a <- x
b <- y
return (a, b)
and I tested it with three different monads:
main = do
putStrLn $ show $ combine (Just 10) (Just 20) -- Maybe a
putStrLn $ show $ combine [100] [10, 20] -- [] a
a <- combine getLine getLine -- IO a
putStrLn $ show a
And it works great as expected. Now, I want to know if Scala's type-system could allow me to write the above function without compromising the genericity. But I don't know Scala enough (though I wish to explore it). So could anyone help me convert this code into Scala?
I think this is the equivalent:
import cats._
import cats.implicits._
def combine[T, F[_]: Monad](fa: F[T], fb: F[T]) = for {
a <- fa
b <- fb
} yield (a, b)
Where Monad is from a library (cats or scalaz).
combine(Option(10), Option(20)) produces Some((10,20)) and combine(List(100), List(10, 20)) produces List((100,10), (100,20)).
EDIT: The above version is over-constrained, since it requires the two argument types to be the same. def combine[A, B, F[_]: Monad](fa: F[A], fb: F[B]) fixes that.
Your combine function is equivalent to the Scala code
for { a <- x; b <- y } yield (a,b)
So you might try defining a function:
def combine[M[_],A,B](x: M[A], y: M[B]): M[(A,B)] =
for { a <- x; b <- y } yield (a,b)
And the compiler will complain that flatMap is not a member of M[A] and map is not a member of M[B].
The thing with for is that it is a bit of compiler magic that will accept any type that implements functions called map, flatMap, and withFilter. This is in contrast to Haskell in which we can add (or let the compiler infer) a Monad constraint to let do notation work.
To expand on the answer #JoePallas gave, it is possible to make this work. In fact, the following implementation is essentially how GHC implements typeclasses. The cats and scalaz libraries provide all this stuff for you, but this is how the sausage is made:
First define the interface we need:
trait For[M[_]] {
def map[A,B](ma: M[A], f: A => B): M[B]
def flatMap[A,B](ma: M[A],f: A => M[B]): M[B]
def withFilter[A](ma: M[A],q: A => Boolean): M[A]
}
(I'm using the name For and using a slightly different interface than Monad.)
Then we provide an implicit implementation of this trait for every data type we want to support. Here's an example for Option:
implicit val optionFor = new For[Option] {
def map[A,B](ma: Option[A], f: A => B): Option[B] = ma.map(f)
def flatMap[A,B](ma: Option[A],f: A => Option[B]): Option[B] = ma.flatMap(f)
def withFilter[A](ma: Option[A],q: A => Boolean): Option[A] = ma.withFilter(q).map(a => a)
}
Then we provide an implicit conversion to a type that can apply these operations:
implicit class ForOps[M[_], A](val ma: M[A]) extends AnyVal {
def map[B](f: A => B)(implicit m: For[M]): M[B] = m.map(ma,f)
def flatMap[B](f: A => M[B])(implicit m: For[M]): M[B] = m.flatMap(ma, f)
def withFilter(q: A => Boolean)(implicit m: For[M]): M[A] = m.withFilter(ma,q)
}
And finally, we can define combine:
def combine[M[_]: For, A, B](ma: M[A], mb: M[B]): M[(A, B)] =
for { a <- ma; b <- mb } yield (a, b)
The syntax
def f[T: TC] = ???
is sugar for
def f[T](implicit unutterableName: TC[T]) = ???
An implicit argument list, if not given explicitly at the call site, will be automatically filled in by searching for values/functions with the correct types, as long as those are themselves implicit. In this case, we look for a proof that M is a monad. In the body, this value is implicit, and it has no name to access it. Implicit search can still find it. ForOps allows the 3 for operations to automagically appear on the values by using that Monad.
This is really an explicit version of how GHC implements typeclasses. In the simplest case of no optimization:
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
compiles to
data Monad m = Monad {
monadSubApplicative :: Applicative m
return :: forall a. a -> m a
(>>=) :: forall a. m a -> (a -> m b) -> m b
}
and
instance Monad [] where
return = _
(>>=) = _
becomes
monadList :: Monad []
monadList = Monad {
monadSubApplicative = applicativeList
, return = _
, (>>=) = _
}
You will often hear the word "dictionary" be used to describe the underlying data type and values. And combine is
combine :: Monad m -> m a -> m b -> m (a, b)
combine (Monad _ return (>>=)) ma mb = ma >>= \a -> mb >>= \b -> return (a, b)
However, GHC applies a bunch of restrictions to the system that makes it more predictable and performs more optimization. Scala sacrifices this to allow the programmer to perform more interesting acrobatics.
For good measure, an instance like this:
newtype Compose f g a = Compose { unCompose :: f (g a) }
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fga) = Compose $ fmap (fmap f) fga
would be done like this in Scala (using an implicit def, not a val):
trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] }
final case class Compose[F[_], G[_], A](val get: F[G[A]]) extends AnyVal
object Compose {
// you usually put these implicits in the associated companions
// because implicit search is picky about where it looks
implicit def functor[F[_], G[_]](implicit
functorF: Functor[F],
functorG: Functor[G]
// type lambda: use a type projection on a refinement type
// to create an anonymous type-level function
// it's universally accepted as a horrendous abuse of syntax
// you can use the kind-projector plugin to avoid writing them (directly)
) : Functor[({type L[X] = Compose[F, G, X]})#L]
= new Functor[({type L[X] = Compose[F, G, X]})#L] {
override def map[A, B](cfga: Compose[F, G, A])(f: A => B): Compose[F, G, B] =
Compose(functorF.map(cfga.get) { ga => functorG.map(ga)(f) })
}
}
Making all this stuff explicit is a bit ugly, but it works quite well.
In functional programming (and programming in general) it is good practice to use the least powerful abstraction you can find. In the example you gave, you actually don't need the power of a monad. The combine function is liftA2 from the applicative type class. Example:
import Data.Maybe
import Control.Applicative
z= Just 1
y= Just 2
liftA2 (,) z y
> Just (1,2)
In Scala you have something similar. An example from the Scalaz library which uses the same abstraction:
import scalaz._, Scalaz._
(Option(1) |#| Option(2))(Tuple2.apply)
> res3: Option[(Int, Int)] = Some((1, 2))
The reason you don't need the monad abstraction is that the values are independent of each other.
Let's say I have two functions val f: A => M[B] and val g: B => M[C] where M is monadic. Thus I want to combine them by using kleisli.
What I currently do is this: kleisliU(f) andThenK g
But I have not found a way to execute this combination without manually wrapping into kleisli first.
How can write something like f <???> g so that f is wrapped into kleisli automatically and then combined with g? I hope something in scalaz already exists for that and that I don't need to write my own implicit class / conversion.
Just for sake of completeness, that should also work with more functions e.g. f <???> g <???> h.
Once I wanted the same thing and I did not find it in scalaz, so I just wrote it myself:
implicit def toKleisliK[M[_], A, B]: (A => M[B]) => Kleisli[M, A, B] = f => {
kleisli[M, A, B](a => f(a))
}
// then for example you can write such:
val f: Int => Option[String] = ???
val g: String => Option[Double] = ???
val result = f andThenK g // inferred type is ReaderT[Option, Int, Double]
I want to programmatically compose several functions. If these functions are all of the same type, I can do the following:
def a(x: Int): Int = x+1
def b(y: Int): Int = y/2
def c(z: Int): Int = z*4
val f1 = (a _) andThen (b _) andThen (c _)
val f2 = List((a _), (b _), (c _)).reduce(_ andThen _)
At which point f1 and f2 are the same thing, and this compiles because the List that defines f2 is a List[Function1[Int,Int]]
However, if I want to chain together multiple compatible functions with different types using the same basic reduce technique, I get an error.
def d(x: Double): Int = x.toInt
def e(y: Int): String = y.toString
def f(z: String): Double = z.toDouble*4
//Works fine
val f3 = (d _) andThen (e _) andThen (f _)
//Doesn't compile
val f4 = List((d _), (e _), (f _)).reduce(_ andThen _)
The second option doesn't compile because the list that defines f4 is inferred as a List[Function1[Any,Any]], but I can't figure out if theres a clean type-safe way to take an ordered collection of functions of the form Function1[A,B],Function1[B,C],Function1[C,D],...,Function1[X,Y] and glue them together as a Function1[A,Y] like this.
Any ideas?
There are two problems here. The first (as you've noted) is that the list has a single element type, which will be inferred to be the least upper bound of the types of the elements it contains, which in this case is the extremely boring and useless String with Int with Double => Any. Heterogeneous lists provide one way of addressing this part of the problem, as I'll show in a second.
The second problem is that the _ andThen _ is insufficiently polymorphic (as Bob Dalgleish points out in a comment above). The argument to reduce will be a function with a concrete input type and a concrete output type, so even if we had a heterogeneous list, there's no way we could reduce it with a Function from the Scala standard library—we'd need a polymorphic function value instead.
Fortunately (if you really want to do this kind of thing in Scala), there's a great library called Shapeless that provides nice implementations of both heterogeneous lists and polymorphic functions. For example, you could write the following:
def d(x: Double): Int = x.toInt
def e(y: Int): String = y.toString
def f(z: String): Double = z.toDouble * 4
import shapeless._
object andThen extends Poly2 {
implicit def functions[A, B, C] = at[A => B, B => C](_ andThen _)
}
And then:
scala> val andThenned = HList((d _), (e _), (f _)).reduceLeft(andThen)
andThenned: Double => Double = <function1>
scala> andThenned(13.0)
res0: Double = 52.0
I think this is pretty neat.
I'm interested in encoding this Stream type from the Stream Fusion paper from Coutts et al. I'm exploring stream fusion in Scala, attempting to use macros in place of GHC's rewrite rules.
data Stream a = ∃s. Stream (s → Step a s) s
data Step a s = Done
| Yield a s
| Skip s
I've tried a few different approaches but I'm not sure how to encode the type of Stream in Scala such that both occurrences of S refer to the same type. I've written the Step type easily as.
sealed abstract class Step[+A, +S]
case object Done extends Step[Nothing, Nothing]
case class Yield[A, S](a: A, s: S) extends Step[A, S]
case class Skip[S](s: S) extends Step[Nothing, S]
So far this type seems correct. I've used covariance so that a function of type A => A will work even if we receive a Yield and return a Done or Step. Just like in Haskell.
My sticking point has been the signature of Stream. I've been attempting to define it as just a case class. The only signature that has worked so far is using an Exists type operator and Tuple to perserve the equality of type S in both components as below.
type Exists[P[_]] = P[T] forSome { type T }
case class Stream[A](t: Exists[({ type L[S] = (S => Step[A, S], S)})#L])
Is there a way to encode it such that the tuple is not needed? Something closer to Haskell's (assuming existential operator) this:
case class Stream(∃ S. f: S => Step[A, S], s: S)
where each member can be separate field.
It also occurs to me that I could encode this in an SML Module/Functor style like so:
trait Stream[A] {
type S <: AnyRef
val f: S => Step[A, S]
val s: S
}
object Stream {
def apply[A, S1 <: AnyRef](next: S1 => Step[A, S1], st: S1): Stream[A] = new Stream[A] {
type S = S1
val f = next
val s = st
}
def unapply[A](s: Stream[A]): Option[(s.f.type, s.s.type)] = Some(s.f, s.s)
}
but this is a little more complicated. I was hoping there exists a clearer way, that I am ignorant of. Also as I attempted to explore this path, I had to do a few things to satisfy the compiler such as add the AnyRef bound, and the unapply method doesn't work. With this error message from scalac:
scala> res2 match { case Stream(next, s) => (next, s) }
<console>:12: error: error during expansion of this match (this is a scalac bug).
The underlying error was: type mismatch;
found : Option[(<unapply-selector>.f.type, <unapply-selector>.s.type)]
required: Option[(s.f.type, s.s.type)]
res2 match { case Stream(next, s) => (next, s) }
^
First off, Step looks perfect to me. As for Stream, I think you're on the right track with the abstract type. Here's what I came up with (including implementations of the remaining methods in section 2.1 of the Coutts paper):
abstract class Stream[A] {
protected type S
def next: S => Step[A, S]
def state: S
def map[B](f: A => B): Stream[B] = {
val next: S => Step[B, S] = this.next(_) match {
case Done => Done
case Skip(s) => Skip(s)
case Yield(a, s) => Yield(f(a), s)
}
Stream(next, state)
}
def unstream: List[A] = {
def unfold(s: S): List[A] = next(s) match {
case Done => List.empty
case Skip(s) => unfold(s)
case Yield(a, s) => a :: unfold(s)
}
unfold(state)
}
}
object Stream {
def apply[A, S0](n: S0 => Step[A, S0], s: S0) = new Stream[A] {
type S = S0
val next = n
val state = s
}
def apply[A](as: List[A]): Stream[A] = {
val next: List[A] => Step[A, List[A]] = {
case a :: as => Yield(a, as)
case Nil => Done
}
Stream(next, as)
}
def unapply[A](s: Stream[A]): Option[(s.S => Step[A, s.S], s.S)] =
Some((s.next, s.state))
}
A couple things to note:
My unapply has a dependent method type: it depends on the s.S. I think that might have been your stumbling block.
The unfold method in unstream is not tail-recursive.
The thing I'm still not really clear on myself is why it's important for S to be existential / hidden / whatever. If it's not, you could just write:
case class Stream[A, S](next: S => Step[A, S], state: S)
... but I assume there's a reason for it. That being said, I'm also not sure this approach actually hides S the way you want. But this is my story and I'm sticking to it.
I would like to map the elements of a Scala tuple (or triple, ...) using a single function returning type R. The result should be a tuple (or triple, ...) with elements of type R.
OK, if the elements of the tuple are from the same type, the mapping is not a problem:
scala> implicit def t2mapper[A](t: (A,A)) = new { def map[R](f: A => R) = (f(t._1),f(t._2)) }
t2mapper: [A](t: (A, A))java.lang.Object{def map[R](f: (A) => R): (R, R)}
scala> (1,2) map (_ + 1)
res0: (Int, Int) = (2,3)
But is it also possible to make this solution generic, i.e. to map tuples that contain elements of different types in the same manner?
Example:
class Super(i: Int)
object Sub1 extends Super(1)
object Sub2 extends Super(2)
(Sub1, Sub2) map (_.i)
should return
(1,2): (Int, Int)
But I could not find a solution so that the mapping function determines the super type of Sub1 and Sub2. I tried to use type boundaries, but my idea failed:
scala> implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
<console>:8: error: X is already defined as type X
implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
^
<console>:8: error: type mismatch;
found : A
required: X
Note: implicit method t2mapper is not applicable here because it comes after the application point and it lacks an explicit result type
implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
Here X >: B seems to override X >: A. Does Scala not support type boundaries regarding multiple types? If yes, why not?
I think this is what you're looking for:
implicit def t2mapper[X, A <: X, B <: X](t: (A,B)) = new {
def map[R](f: X => R) = (f(t._1), f(t._2))
}
scala> (Sub1, Sub2) map (_.i)
res6: (Int, Int) = (1,2)
A more "functional" way to do this would be with 2 separate functions:
implicit def t2mapper[A, B](t: (A, B)) = new {
def map[R](f: A => R, g: B => R) = (f(t._1), g(t._2))
}
scala> (1, "hello") map (_ + 1, _.length)
res1: (Int, Int) = (2,5)
I’m not a scala type genius but maybe this works:
implicit def t2mapper[X, A<:X, B<:X](t: (A,B)) = new { def map[A, B, R](f: X => R) = (f(t._1),f(t._2)) }
This can easily be achieved using shapeless, although you'll have to define the mapping function first before doing the map:
object fun extends Poly1 {
implicit def value[S <: Super] = at[S](_.i)
}
(Sub1, Sub2) map fun // typed as (Int, Int), and indeed equal to (1, 2)
(I had to add a val in front of i in the definition of Super, this way: class Super(val i: Int), so that it can be accessed outside)
The deeper question here is "why are you using a Tuple for this?"
Tuples are hetrogenous by design, and can contain an assortment of very different types. If you want a collection of related things, then you should be using ...drum roll... a collection!
A Set or Sequence will have no impact on performance, and would be a much better fit for this kind of work. After all, that's what they're designed for.
For the case when the two functions to be applied are not the same
scala> Some((1, "hello")).map((((_: Int) + 1 -> (_: String).length)).tupled).get
res112: (Int, Int) = (2,5)
The main reason I have supplied this answer is it works for lists of tuples (just change Some to List and remove the get).