Composable using scalaz Arrow? - scala

I have two functions.
def process(date: DateTime, invoice: Invoice, user: User, reference: Reference) : (Action, Iterable[Billable])
def applyDiscount(billable: Billable) : Billable
How can I compose these so that I have a single function of (DateTime, Invoice, User, Reference) => (Action, Iterable[Billable])
Here is the poor mans way of what I want
def buildFromInvoice(user: User, order: Invoice, placementDate: DateTime, reference: Reference) = {
val ab = billableBuilder.fromInvoice(user, order, placementDate, reference)
(ab._1, ab._2.map(applyDiscount(_))
}

What you have (simplifying) is:
val f: A => (B, M[C]) //M is a Functor
val g: C => C
I can think of a few ways of doing this. I think my preference is:
(a: A) => g.lift[M].second apply f(a)
Or also:
(a: A) => f(a) :-> g.lift[M]
However, there is possibly a pointfree way - although not necessarily so, of course
lift is a method on Function1W which lifts the function into the realm of the functor M
second is a method on MAB which applies the function down the right-hand-side of a Bifunctor
:-> is a method available to Bifunctors denoting the application of a function on the rhs.
EDIT - missingfaktor appears to be correct in saying f andThen g.lift[M].second works:
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> case class A(); case class B(); case class C()
defined class A
defined class B
defined class C
scala> lazy val f: A => (B, List[C]) = sys.error("")
f: A => (B, List[C]) = <lazy>
scala> lazy val g: C => C = sys.error("")
g: C => C = <lazy>
Pointfree:
scala> lazy val h = f andThen g.lift[List].second
h: A => (B, List[C]) = <lazy>

Related

is it possible to implement flip as a Scala function (and not a method)

As a part of learning Scala I try to implement Haskell's flip function (a function with signature (A => B => C) => (B => A => C)) in Scala - and implement it as a function (using val) and not as a method (using def).
I can implement it as a method, for instance this way:
def flip[A, B, C](f: (A, B) => C):((B, A) => C) = (b: B, a: A) => f(a, b)
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))
However, when I try to implement it as a function, it does not work:
val flip = (f: ((Any, Any) => Any)) => ((a: Any, b: Any) => f(b, a))
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))
When I try to compile this code, it fails with this message:
Error:(8, 18) type mismatch;
found : (Int, Int) => Int
required: (Any, Any) => Any
val f = flip(minus)
I understand why it fails: I try to pass (Int, Int) => Int where (Any, Any) => Any is expected. However, I don't know how to fix this problem. Is it possible at all?
Scala doesn't support polymorphic functions, unlike methods which are. This is due to the first class value nature of functions, which are simply instances of the FunctioN traits. These functions are classes, and they need the types to be bound at declaration site.
If we took the flip method and tried to eta expand it to a function, we'd see:
val flipFn = flip _
We'd get back in return a value of type:
((Nothing, Nothing) => Nothing) => (Nothing, Nothing) => Nothing
Due to the fact that none of the types were bound, hence the compiler resorts to the buttom type Nothing.
However, not all hope is lost. There is a library called shapeless which does allow us to define polymorphic functions via PolyN.
We can implement flip like this:
import shapeless.Poly1
object flip extends Poly1 {
implicit def genericCase[A, B, C] = at[(A, B) => C](f => (b: B, a: A) => f(a, b))
}
flip is no different from the FunctionN trait, it defines an apply method which will be called.
We use it like this:
def main(args: Array[String]): Unit = {
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))
}
Yielding:
2
This would also work for String:
def main(args: Array[String]): Unit = {
val stringConcat = (a: String, b: String) => a + b
val f = flip(stringConcat)
println(f("hello", "world"))
}
Yielding:
worldhello

Map `State` via `Lens`

Is there some function with signature like
lensMapState[S, T, A](lens : Lens[S, T]): State[T, A] => State[S, A]
With semantics run modification of chosen part and get result
One implementation could be
def lensMapState[S, T, A](lens: Lens[S, T]): State[T, A] => State[S, A] =
stateT => State { s =>
val (result, x) = stateT.run(lens.get(s))
(lens.set(result)(s), x)
}
but if there more straightforward way using monocle or scalaz.Lens ?
I think what you are looking for is something like this:
import scalaz._
import Scalaz._
case class Person(name: String, age: Int)
case object Person {
val _age = Lens.lensu[Person, Int]((p, a) => p.copy(age = a), _.age
}
val state = for {
a <- Person._age %= { _ + 1 }
} yield a
state.run(Person("Holmes", 42))
which results in
res0: scalaz.Id.Id[(Person, Int)] = (Person(Holmes,43),43)
There are many lens/state related functions defined in https://github.com/scalaz/scalaz/blob/series/7.1.x/core/src/main/scala/scalaz/Lens.scala
Monocle follows a similiar principle. The related functions are defined in monocle.state as far as I know.

How to get generic (polymorphic) lambda in scala?

Update (2018): my prayers were answered in Dotty (Type Lambdas), so the following Q&A is more "Scala 2.x"-related
Just a simple example from Scala:
scala> def f(x: Int) = x
f: (x: Int)Int
scala> (f _)(5)
res0: Int = 5
Let's make it generic:
scala> def f[T](x: T) = x
f: [T](x: T)T
scala> (f _)(5)
<console>:9: error: type mismatch;
found : Int(5)
required: Nothing
(f _)(5)
^
Let's look at eta-expansion of polymorphic method in Scala:
scala> f _
res2: Nothing => Nothing = <function1>
Comparison with Haskell:
Prelude> let f x = x
Prelude> f 5
5
Prelude> f "a"
"a"
Prelude> :t f
f :: t -> t
Haskell did infer correct type [T] => [T] here.
More realistic example?
scala> identity _
res2: Nothing => Nothing = <function1>
Even more realistic:
scala> def f[T](l: List[T]) = l.head
f: [T](l: List[T])T
scala> f _
res3: List[Nothing] => Nothing = <function1>
You can't make alias for identity - have to write your own function. Things like [T,U](t: T, u: U) => t -> u (make tuple) are impossible to use as values. More general - if you want to pass some lambda that rely on generic type (e.g. uses generic function, for example: creates lists, tuples, modify them in some way) - you can't do that.
So, how to solve that problem? Any workaround, solution or reasoning?
P.S. I've used term polymorphic lambda (instead of function) as function is just named lambda
Only methods can be generic on the JVM/Scala, not values. You can make an anonymous instance that implements some interface (and duplicate it for every type-arity you want to work with):
trait ~>[A[_], B[_]] { //exists in scalaz
def apply[T](a: A[T]): B[T]
}
val f = new (List ~> Id) {
def apply[T](a: List[T]) = a.head
}
Or use shapeless' Poly, which supports more complicated type-cases. But yeah, it's a limitation and it requires working around.
P∀scal is a compiler plugin that provides more concise syntax for encoding polymorphic values as objects with a generic method.
The identity function, as a value, has type ∀A. A => A. To translate that into Scala, assume a trait
trait ForAll[F[_]] {
def apply[A]: F[A]
}
Then the identity function has type ForAll[λ[A => A => A]], where I use the kind-projector syntax, or, without kind-projector:
type IdFun[A] = A => A
type PolyId = ForAll[IdFun]
And now comes the P∀scal syntactic sugar:
val id = Λ[Α](a => a) : PolyId
or equivalently
val id = ν[PolyId](a => a)
("ν" is the Greek lowercase letter "Nu", read "new")
These are really just shorthands for
new PolyId {
def apply[A] = a => a
}
Multiple type parameters and parameters of arbitrary kinds are supported by P∀scal, but you need a dedicated variation on the above ForAll trait for each variant.
I really like #Travis Brown 's solution:
import shapeless._
scala> Poly(identity _)
res2: shapeless.PolyDefns.~>[shapeless.Id,shapeless.Id] = fresh$macro$1$2$#797aa352
-
scala> def f[T](x: T) = x
f: [T](x: T)T
scala> Poly(f _)
res3: shapeless.PolyDefns.~>[shapeless.Id,shapeless.Id] = fresh$macro$2$2$#664ea816
-
scala> def f[T](l: List[T]) = l.head
f: [T](l: List[T])T
scala> val ff = Poly(f _)
ff: shapeless.PolyDefns.~>[List,shapeless.Id] = fresh$macro$3$2$#51254c50
scala> ff(List(1,2,3))
res5: shapeless.Id[Int] = 1
scala> ff(List("1","2","3"))
res6: shapeless.Id[String] = 1
Poly constructor (in some cases) will give you eta-expansion into Shapeless2 Poly1 function, which is (more-less) truly generic. However it doesn't work for multi-parameters (even with multi type-parameters), so have to "implement" Poly2 with implicit + at approach (as #som-snytt suggested), something like:
object myF extends Poly2 {
implicit def caseA[T, U] = at[T, U]{ (a, b) => a -> b}
}
scala> myF(1,2)
res15: (Int, Int) = (1,2)
scala> myF("a",2)
res16: (String, Int) = (a,2)
P.S. I would really want to see it as a part of language.
It seems to do this you will need to do a bit type hinting to help the Scala type inference system.
def id[T] : T => T = identity _
So I guess if you try to pass identity as a parameter to a function call and the types of that parameter are generic then there should be no problem.

Tupled function outputs

I'm looking for a function that takes a tuple of functions over a common domain and returns a function from that domain to a tuple of their respective outputs. I'm assuming that such a utility is either built into Scala or is tucked away somewhere in Scalaz, but I have been unable to find it.
For example, the special case of a pair of functions (and taking the functions as individual arguments rather than a pair) would look like:
def pairFunc[I, O1, O2](f: I => O1, g: I => O2): I => (O1, O2) = (x: I) => (f(x), g(x))
Is there a way to achieve this for an arbitrary-arity tuple of functions?
EDIT:
A method on a Function type whose output looks like X -> ((A, B), C) and whose construction looks like f fZip g fZip h is just as fine as one a function whose output is X -> (A, B, C).
You're in luck, scalaz (7) does have this with &&&:
import scalaz._
import Scalaz._
val intToString = (i:Int) => i.toString
val intPlusTwo = (i:Int) => i + 2
val combined = intToString &&& intPlusTwo
println(combined(1)) // (1, 3)
And you can continue to combine though it does build up tuples per what your comments would suggest:
val combinedMore = intToString &&& intPlusTwo &&& intToString
println(combinedMore(1)) // ((1,3),1)
You can define your own implicits and chain them using view bounds <%
// Add untupling capacity to a simple pair
implicit class EnrichTuple [A, B, C](f: (Function1[A, B], Function1[A, C])) {
def untuple = (a: A) => (f._1(a), f._2(a))
}
// Add untupling capacity to a pair where the first member can implicitly be untupled
implicit class EnrichTuple2 [A, C, AB <% Function1[A, B] forSome { type B }](f: (AB, Function1[A, C])) {
def untuple = (a: A) => (f._1(a), f._2(a))
}
// Add untupling capacity to a pair where the second member can implicitly be untupled
implicit class EnrichTuple3 [A, B, AC <% Function1[A, C] forSome { type C }](f: (Function1[A, B], AC)) {
def untuple = (a: A) => (f._1(a), f._2(a))
}
val intToString = (i:Int) => i.toString
val intPlusTwo = (i:Int) => i + 2
val intTimesFour = (i: Int) => i * 4
val res1 = (intToString, intPlusTwo).untuple
val res2 = ((intToString, intPlusTwo), intTimesFour).untuple
val res3 = (intToString, (intPlusTwo, intTimesFour)).
res1(1) // Returns (1, 3)
res2(1) // Returns ((1, 3),4)
res3(1) // Returns (1, (3, 4))
val res4 = ((intToString, intTimesFour), (intPlusTwo, intTimesFour )).untuple // Error
The thing you also loose compared to the scalaz solution is the type of the result if there are nested tuples. And besides, you have the requirement that each time at least one of the two arguments of your pair is already a function.

Scala PartialFunction can be Monoid?

I thought PartialFunction can be Monoid. Is my thought process correct ?
For example,
import scalaz._
import scala.{PartialFunction => -->}
implicit def partialFunctionSemigroup[A,B]:Semigroup[A-->B] = new Semigroup[A-->B]{
def append(s1: A-->B, s2: => A-->B): A-->B = s1.orElse(s2)
}
implicit def partialFunctionZero[A,B]:Zero[A-->B] = new Zero[A-->B]{
val zero = new (A-->B){
def isDefinedAt(a:A) = false
def apply(a:A) = sys.error("error")
}
}
But current version Scalaz(6.0.4) is not included it. Is there a reason for something not included ?
Let's shine a different light on this.
PartialFunction[A, B] is isomorphic to A => Option[B]. (Actually, to be able to check if it is defined for a given A without triggering evaluation of the B, you would need A => LazyOption[B])
So if we can find a Monoid[A => Option[B]] we've proved your assertion.
Given Monoid[Z], we can form Monoid[A => Z] as follows:
implicit def readerMonoid[Z: Monoid] = new Monoid[A => Z] {
def zero = (a: A) => Monoid[Z].zero
def append(f1: A => Z, f2: => A => Z) = (a: A) => Monoid[Z].append(f1(a), f2(a))
}
So, what Monoid(s) do we have if we use Option[B] as our Z? Scalaz provides three. The primary instance requires a Semigroup[B].
implicit def optionMonoid[B: Semigroup] = new Monoid[Option[B]] {
def zero = None
def append(o1: Option[B], o2: => Option[B]) = o1 match {
case Some(b1) => o2 match {
case Some(b2) => Some(Semigroup[B].append(b1, b2)))
case None => Some(b1)
case None => o2 match {
case Some(b2) => Some(b2)
case None => None
}
}
}
Using this:
scala> Monoid[Option[Int]].append(Some(1), Some(2))
res9: Option[Int] = Some(3)
But that's not the only way to combine two Options. Rather than appending the contents of the two options in the case they are both Some, we could simply pick the first or the last of the two. Two trigger this, we create a distinct type with trick called Tagged Types. This is similar in spirit to Haskell's newtype.
scala> import Tags._
import Tags._
scala> Monoid[Option[Int] ## First].append(Tag(Some(1)), Tag(Some(2)))
res10: scalaz.package.##[Option[Int],scalaz.Tags.First] = Some(1)
scala> Monoid[Option[Int] ## Last].append(Tag(Some(1)), Tag(Some(2)))
res11: scalaz.package.##[Option[Int],scalaz.Tags.Last] = Some(2)
Option[A] ## First, appended through it's Monoid, uses the same orElse semantics as your example.
So, putting this all together:
scala> Monoid[A => Option[B] ## First]
res12: scalaz.Monoid[A => scalaz.package.##[Option[B],scalaz.Tags.First]] =
scalaz.std.FunctionInstances0$$anon$13#7e71732c
No, this looks good, satisfying both the requirements for (non-commutative) Monoid. Interesting idea. What use case are you trying to support?
Your zero certainly violates the axiom for the identity element, but I think the identity (partial) function would be OK.
Your append also doesn't fulfill the Monoid laws, but instead of orElse you could call andThen (composition). But this would only work for A == B:
implicit def partialFunctionSemigroup[A]: Semigroup[A --> A] = new Semigroup[A --> A] {
def append(s1: A --> A, s2: => A --> A): A-->A = s1 andThen s2
}
implicit def partialFunctionZero[A]: Zero[A --> A] = new Zero[A --> A] {
val zero = new (A --> A) {
def isDefinedAt(a:A) = true
def apply(a:A) = a
}
}