I fail to implement a function that returns a recursive match type. As an example, I took the tuple Append type from the std lib and tried to implement a simple append function.
// Tuple append match type, copied from std lib
type Append[X <: Tuple, Y] <: Tuple = X match {
case EmptyTuple => Y *: EmptyTuple
case x *: xs => x *: Append[xs, Y]
}
// Types work just fine
val x: Append[(String, Int), Long] = ("", 1, 2L)
// My simple function implementation that does not compile
def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x match
case _: EmptyTuple => y *: EmptyTuple
case x *: xs => x *: append(xs, y)
[E007] Type Mismatch Error:
case _: EmptyTuple => y *: EmptyTuple
^^^^^^^^^^^^^^^
Found: Y *: EmptyTuple.type
Required: Append[X, Y]
where: X is a type in method append with bounds <: Tuple
Note: a match type could not be fully reduced:
trying to reduce Append[X, Y]
failed since selector X
does not match case EmptyTuple => Y *: EmptyTuple
and cannot be shown to be disjoint from it either.
Therefore, reduction cannot advance to the remaining case
case x *: xs => x *: Append[xs, Y]
longer explanation available when compiling with `-explain`
[E007] Type Mismatch Error:
case x *: xs => x *: append(xs, y)
^^^^^^^^^^^^^^^^^^
Found: Any *: Append[Tuple, Y]
Required: Append[X, Y]
where: X is a type in method append with bounds <: Tuple
Note: a match type could not be fully reduced:
trying to reduce Append[Tuple, Y]
failed since selector Tuple
does not match case EmptyTuple => Y *: EmptyTuple
and cannot be shown to be disjoint from it either.
Therefore, reduction cannot advance to the remaining case
case x *: xs => x *: Append[xs, Y]
longer explanation available when compiling with `-explain`
Scastie
The compiler is very fussy when it comes to returning match types. Your second case needs a small modification to get it to work without the cast (Scastie):
def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x.match {
case _: EmptyTuple => y *: EmptyTuple
case (x *: xs): (x *: xs) => x *: append(xs, y)
}
Without the : (x *: xs), the compiler doesn't understand that your function's second case corresponds with the second case of the match type. Perhaps in the future it'll be smarter.
A cast in the append function did the trick. I couldn't manage to inline it, but this is sufficient for now.
// Tuple append match type, copied from std lib
type Append[X <: Tuple, Y] <: Tuple = X match {
case EmptyTuple => Y *: EmptyTuple
case x *: xs => x *: Append[xs, Y]
}
// Types work just fine
val x: Append[(String, Int), Long] = ("", 1, 2L)
// Function now compiles and succeeds at runtime
def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x.match {
case _: EmptyTuple => y *: EmptyTuple
case x *: xs => x *: append(xs, y)
}.asInstanceOf[Append[X, Y]]
append((1, 2), 3)
Scastie
As mentioned in the title i don't understand why these function doesn't compile and are asking for a Seq.
def f1[V <: Seq[Int]](v: V): V = v.map(_ + 1)
def f2[V <: Seq[Int]](v: V): V = v.zip(v).map{ case (a, b) => a + b }
error: type mismatch;
found : Seq[Int]
required: V
I have the following workaround :
def f1[V <: Seq[Int]](v: V): V = v.map(_ + 1).asInstanceOf[V]
def f2[V <: Seq[Int]](v: V): V = v.zip(v).map{ case (a, b) => a + b }.asInstanceOf[V]
But i would like to know if it exist another solution. If not what is the cost of casting something like that, is it O(1) or O(n) with n the Seq size.
Because
v.map(_ + 1).asInstanceOf[V]
can easily fail: map is only guaranteed to return a Seq[Int], which may or may not happen to be an instance of V when you run the code.
One example would be V = SeqView.Filtered, where map returns a SeqView.Mapped.
If not what is the cost of casting something like that, is it O(1) or O(n) with n the Seq size.
The cost of casting with asInstanceOf is always O(1). In some cases it's actually a no-op and the cost is 0.
Let's go through how your function is compiled:
def f1[V <: Seq[Int]](v: V): V = v.map(_ + 1)
1/ You declared V as a sub-type of Seq[Int]. So V can be viewed by the compiler as Seq[Int].
2/ Inside function, v.map(_ + 1) return type is Seq[Int] because it's using a Seq method.
3/ V is the declared return type. This doesn't match the actual return type, which is Seq[Int]. And your compiler can't view Seq[Int] as V because because there's no type bound that says [V >: Seq[Int]].
So I have a generic compose combinator.
Recall that the composition of two functions—f and g-- is h(x) = f(g(x))
def inc(x: Double) = x + 1
def double(x: Double) = 2 * x
def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x))
//TEST
println(compose(double, inc, 2.0))
//OUTPUT
// 6.0
But now I want to implement the self-composition iterator combinator, recursively, using my compose function where:
def selfIter[T](f: T=>T, n: Int) = f composed with itself n times.
I tried doing this:
def selfIter[T](f: T, n: Int): T = {
if(n == 0) f
else f + selfIter(f, n-1)
}
//TEST
println(selfIter(compose(double, inc, 2.0), 2))
I get an error, I know I'm doing something fundamentally wrong, but I cant figure out what I need to do.
In this case, the output should be 14.0 because first call will be 2(2+1) = 6.0, and then second call will be 2(6.0 + 1) = 14.0
Question: How should I refactor my code so that selfIter will compose f with itself n times until we have n == 0, and returns the final value
The easiest way to solve this kind of problems is to use the combinators provided by Scala. Also you should first compose the function you want to use and then apply the input
def compose[A,B,C](f: B => C, g: A => B): A => C = g.andThen(f)
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f))
println(selfIter(compose(double, inc), 2)(2.0))
If compose signature could not be changed then
def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x))
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f))
println(selfIter[Double](compose(double, inc, _), 2)(2.0))
But it makes much more sense the first solution
There are a few things going wrong here.
This f + selfIter(f, n-1) says that f (type T) must have a + method that takes another T as an argument. But you don't want to add these things, you want to compose them.
Here's a simpler way to get the result you're after.
Stream.iterate(2.0)(compose(double, inc, _))(2) // res0: Double = 14.0
If you're intent on a recursive method, this appears to achieve your goal.
def selfIter[T](start:T, n:Int)(f:T=>T): T = {
if (n < 2) f(start)
else f(selfIter(start, n-1)(f))
}
selfIter(2.0, 2)(compose(double, inc, _)) // res0: Double = 14.0
OK, so I'm trying to implement the basics of lambda calculus. Here it goes.
My numbers:
def zero[Z](s: Z => Z)(z: Z): Z = z
def one[Z](s: Z => Z)(z: Z): Z = s(z)
def two[Z](s: Z => Z)(z: Z): Z = s(s(z))
Partially (actually, non) applied version of them is smth like that:
def z[Z]: (Z => Z) => (Z => Z) = zero _
Before I continue I define some types:
type FZ[Z] = Z => Z
type FFZ[Z] = FZ[Z] => FZ[Z]
Fine, succ function goes like (Application order should be exactly like that! I took the definition here):
def succ[Z](w: FFZ[Z])(y: FZ[Z])(x: Z): Z = y((w(y))(x))
And the unapplied version of it gets as scary as:
def s[Z]: FFFZ[Z] = successor _
Beg your pardon, here is the missing types:
type FFFZ[Z] = FFZ[Z] => FFZ[Z]
type FFFFZ[Z] = FFFZ[Z] => FFFZ[Z]
But I'm stuck at the add function. If conformed to types and definition (taken here as well) it goes like
def add[Z](a: FFFFZ[Z])(b: FFZ[Z]): FFZ[Z] =
(a(s))(b)
But I want a to be a common number of type FFZ[Z].
So -- how can I define addition?
It's totally possible to implement Church numerals in Scala. Here is one such rather straight-forward implementation:
object ChurchNumerals {
type Succ[Z] = Z => Z
type ChNum[Z] = Succ[Z] => Z => Z
def zero[Z]: ChNum[Z] =
(_: Succ[Z]) => (z: Z) => z
def succ[Z] (num: ChNum[Z]): ChNum[Z] =
(s: Succ[Z]) => (z: Z) => s( num(s)(z) )
// a couple of church constants
def one[Z] : ChNum[Z] = succ(zero)
def two[Z] : ChNum[Z] = succ(one)
// the addition function
def add[Z] (a: ChNum[Z]) (b: ChNum[Z]) =
(s: Succ[Z]) => (z: Z) => a(s)( b(s)(z) )
def four[Z] : ChNum[Z] = add(two)(two)
// test
def church_to_int (num: ChNum[Int]): Int =
num((x: Int) => x + 1)(0)
def fourInt: Int = church_to_int(four)
def main(args: Array[String]): Unit = {
println(s"2 + 2 = ${fourInt}")
}
}
Compiles and prints:
$ scala church-numerals.scala
2 + 2 = 4
If I were to explain Church numerals from scratch I'd add more commentaries. But taking the context into account, I'm not sure on what to comment in this case. Please feel free to ask and I'll add more explanations.
I have coded Numerals, Booleans and Pairs: https://github.com/pedrofurla/church/blob/master/src/main/scala/Church.scala following Church's style.
One thing I noticed is that using the curried function syntax was much easier than using multiple argument lists. Some of the interesting snippets
type NUM[A] = (A => A) => A => A
def succ [A]: NUM[A] => NUM[A] = m => n => x => n(m(n)(x))
def zero [A]: NUM[A] = f => x => x
def one [A]: NUM[A] = f => x => f(x)
def two [A]: NUM[A] = f => x => f(f(x))
def three [A]: NUM[A] = f => x => f(f(f(x)))
def plus [A]: (NUM[A]) => (NUM[A]) => NUM[A] = m => n => f => x => m(f)(n(f)(x))
Now for printing them out (very similar to Antov Trunov's solution):
def nvalues[A] = List(zero[A], one[A], two[A], three[A])
val inc: Int => Int = _ + 1
def num: (NUM[Int]) => Int = n => n(inc)(0)
def numStr: (NUM[String]) => String = n => n("f (" + _ + ") ")("z")
Some output:
scala> println(nvalues map num)
List(0, 1, 2, 3)
scala> println(nvalues map numStr) // Like this better :)
List(z, f (z) , f (f (z) ) , f (f (f (z) ) ) )
I'm guessing that there must be a better functional way of expressing the following:
def foo(i: Any) : Int
if (foo(a) < foo(b)) a else b
So in this example f == foo and p == _ < _. There's bound to be some masterful cleverness in scalaz for this! I can see that using BooleanW I can write:
p(f(a), f(b)).option(a).getOrElse(b)
But I was sure that I would be able to write some code which only referred to a and b once. If this exists it must be on some combination of Function1W and something else but scalaz is a bit of a mystery to me!
EDIT: I guess what I'm asking here is not "how do I write this?" but "What is the correct name and signature for such a function and does it have anything to do with FP stuff I do not yet understand like Kleisli, Comonad etc?"
Just in case it's not in Scalaz:
def x[T,R](f : T => R)(p : (R,R) => Boolean)(x : T*) =
x reduceLeft ((l, r) => if(p(f(l),f(r))) r else l)
scala> x(Math.pow(_ : Int,2))(_ < _)(-2, 0, 1)
res0: Int = -2
Alternative with some overhead but nicer syntax.
class MappedExpression[T,R](i : (T,T), m : (R,R)) {
def select(p : (R,R) => Boolean ) = if(p(m._1, m._2)) i._1 else i._2
}
class Expression[T](i : (T,T)){
def map[R](f: T => R) = new MappedExpression(i, (f(i._1), f(i._2)))
}
implicit def tupleTo[T](i : (T,T)) = new Expression(i)
scala> ("a", "bc") map (_.length) select (_ < _)
res0: java.lang.String = a
I don't think that Arrows or any other special type of computation can be useful here. Afterall, you're calculating with normal values and you can usually lift a pure computation that into the special type of computation (using arr for arrows or return for monads).
However, one very simple arrow is arr a b is simply a function a -> b. You could then use arrows to split your code into more primitive operations. However, there is probably no reason for doing that and it only makes your code more complicated.
You could for example lift the call to foo so that it is done separately from the comparison. Here is a simiple definition of arrows in F# - it declares *** and >>> arrow combinators and also arr for turning pure functions into arrows:
type Arr<'a, 'b> = Arr of ('a -> 'b)
let arr f = Arr f
let ( *** ) (Arr fa) (Arr fb) = Arr (fun (a, b) -> (fa a, fb b))
let ( >>> ) (Arr fa) (Arr fb) = Arr (fa >> fb)
Now you can write your code like this:
let calcFoo = arr <| fun a -> (a, foo a)
let compareVals = arr <| fun ((a, fa), (b, fb)) -> if fa < fb then a else b
(calcFoo *** calcFoo) >>> compareVals
The *** combinator takes two inputs and runs the first and second specified function on the first, respectively second argument. >>> then composes this arrow with the one that does comparison.
But as I said - there is probably no reason at all for writing this.
Here's the Arrow based solution, implemented with Scalaz. This requires trunk.
You don't get a huge win from using the arrow abstraction with plain old functions, but it is a good way to learn them before moving to Kleisli or Cokleisli arrows.
import scalaz._
import Scalaz._
def mod(n: Int)(x: Int) = x % n
def mod10 = mod(10) _
def first[A, B](pair: (A, B)): A = pair._1
def selectBy[A](p: (A, A))(f: (A, A) => Boolean): A = if (f.tupled(p)) p._1 else p._2
def selectByFirst[A, B](f: (A, A) => Boolean)(p: ((A, B), (A, B))): (A, B) =
selectBy(p)(f comap first) // comap adapts the input to f with function first.
val pair = (7, 16)
// Using the Function1 arrow to apply two functions to a single value, resulting in a Tuple2
((mod10 &&& identity) apply 16) assert_≟ (6, 16)
// Using the Function1 arrow to perform mod10 and identity respectively on the first and second element of a `Tuple2`.
val pairs = ((mod10 &&& identity) product) apply pair
pairs assert_≟ ((7, 7), (6, 16))
// Select the tuple with the smaller value in the first element.
selectByFirst[Int, Int](_ < _)(pairs)._2 assert_≟ 16
// Using the Function1 Arrow Category to compose the calculation of mod10 with the
// selection of desired element.
val calc = ((mod10 &&& identity) product) ⋙ selectByFirst[Int, Int](_ < _)
calc(pair)._2 assert_≟ 16
Well, I looked up Hoogle for a type signature like the one in Thomas Jung's answer, and there is on. This is what I searched for:
(a -> b) -> (b -> b -> Bool) -> a -> a -> a
Where (a -> b) is the equivalent of foo, (b -> b -> Bool) is the equivalent of <. Unfortunately, the signature for on returns something else:
(b -> b -> c) -> (a -> b) -> a -> a -> c
This is almost the same, if you replace c with Bool and a in the two places it appears, respectively.
So, right now, I suspect it doesn't exist. It occured to me that there's a more general type signature, so I tried it as well:
(a -> b) -> ([b] -> b) -> [a] -> a
This one yielded nothing.
EDIT:
Now I don't think I was that far at all. Consider, for instance, this:
Data.List.maximumBy (on compare length) ["abcd", "ab", "abc"]
The function maximumBy signature is (a -> a -> Ordering) -> [a] -> a, which, combined with on, is pretty close to what you originally specified, given that Ordering is has three values -- almost a boolean! :-)
So, say you wrote on in Scala:
def on[A, B, C](f: ((B, B) => C), g: A => B): (A, A) => C = (a: A, b: A) => f(g(a), g(b))
The you could write select like this:
def select[A](p: (A, A) => Boolean)(a: A, b: A) = if (p(a, b)) a else b
And use it like this:
select(on((_: Int) < (_: Int), (_: String).length))("a", "ab")
Which really works better with currying and dot-free notation. :-) But let's try it with implicits:
implicit def toFor[A, B](g: A => B) = new {
def For[C](f: (B, B) => C) = (a1: A, a2: A) => f(g(a1), g(a2))
}
implicit def toSelect[A](t: (A, A)) = new {
def select(p: (A, A) => Boolean) = t match {
case (a, b) => if (p(a, b)) a else b
}
}
Then you can write
("a", "ab") select (((_: String).length) For (_ < _))
Very close. I haven't figured any way to remove the type qualifier from there, though I suspect it is possible. I mean, without going the way of Thomas answer. But maybe that is the way. In fact, I think on (_.length) select (_ < _) reads better than map (_.length) select (_ < _).
This expression can be written very elegantly in Factor programming language - a language where function composition is the way of doing things, and most code is written in point-free manner. The stack semantics and row polymorphism facilitates this style of programming. This is what the solution to your problem will look like in Factor:
# We find the longer of two lists here. The expression returns { 4 5 6 7 8 }
{ 1 2 3 } { 4 5 6 7 8 } [ [ length ] bi# > ] 2keep ?
# We find the shroter of two lists here. The expression returns { 1 2 3 }.
{ 1 2 3 } { 4 5 6 7 8 } [ [ length ] bi# < ] 2keep ?
Of our interest here is the combinator 2keep. It is a "preserving dataflow-combinator", which means that it retains its inputs after the given function is performed on them.
Let's try to translate (sort of) this solution to Scala.
First of all, we define an arity-2 preserving combinator.
scala> def keep2[A, B, C](f: (A, B) => C)(a: A, b: B) = (f(a, b), a, b)
keep2: [A, B, C](f: (A, B) => C)(a: A, b: B)(C, A, B)
And an eagerIf combinator. if being a control structure cannot be used in function composition; hence this construct.
scala> def eagerIf[A](cond: Boolean, x: A, y: A) = if(cond) x else y
eagerIf: [A](cond: Boolean, x: A, y: A)A
Also, the on combinator. Since it clashes with a method with the same name from Scalaz, I'll name it upon instead.
scala> class RichFunction2[A, B, C](f: (A, B) => C) {
| def upon[D](g: D => A)(implicit eq: A =:= B) = (x: D, y: D) => f(g(x), g(y))
| }
defined class RichFunction2
scala> implicit def enrichFunction2[A, B, C](f: (A, B) => C) = new RichFunction2(f)
enrichFunction2: [A, B, C](f: (A, B) => C)RichFunction2[A,B,C]
And now put this machinery to use!
scala> def length: List[Int] => Int = _.length
length: List[Int] => Int
scala> def smaller: (Int, Int) => Boolean = _ < _
smaller: (Int, Int) => Boolean
scala> keep2(smaller upon length)(List(1, 2), List(3, 4, 5)) |> Function.tupled(eagerIf)
res139: List[Int] = List(1, 2)
scala> def greater: (Int, Int) => Boolean = _ > _
greater: (Int, Int) => Boolean
scala> keep2(greater upon length)(List(1, 2), List(3, 4, 5)) |> Function.tupled(eagerIf)
res140: List[Int] = List(3, 4, 5)
This approach does not look particularly elegant in Scala, but at least it shows you one more way of doing things.
There's a nice-ish way of doing this with on and Monad, but Scala is unfortunately very bad at point-free programming. Your question is basically: "can I reduce the number of points in this program?"
Imagine if on and if were differently curried and tupled:
def on2[A,B,C](f: A => B)(g: (B, B) => C): ((A, A)) => C = {
case (a, b) => f.on(g, a, b)
}
def if2[A](b: Boolean): ((A, A)) => A = {
case (p, q) => if (b) p else q
}
Then you could use the reader monad:
on2(f)(_ < _) >>= if2
The Haskell equivalent would be:
on' (<) f >>= if'
where on' f g = uncurry $ on f g
if' x (y,z) = if x then y else z
Or...
flip =<< flip =<< (if' .) . on (<) f
where if' x y z = if x then y else z