I am trying to implement basic Boolean logic in lambda calculus in Scala, but I am stuck at the beginning.
I have two types:
type λ_T[T] = T => T
type λ_λ_T[T] = λ_T[T] => T => T
And 'false', that works pretty well:
def λfalse[T]: λ_λ_T[T] = (s: λ_T[T]) => (z: T) => z
But when I try to implement 'true', as It is given in math background of lambda calculus, I get wrong type:
def λtrue[T]: λ_λ_T[T] = (s: λ_T[T]) => (z: T) => s
Outcome error: Expression of type λ_T[T] doesn't conform to expected type T
How can I implement this?
A Church encoding of Booleans is of type
[X] => X -> X -> X
where [X] => means that the X -> X -> X-part is polymorphic in X.
Here are two proposals how you could express this in Scala.
Booleans as generic methods, type inference at call-site
Here is a type that would be appropriate for booleans where the required polymorphic type parameter can be inferred directly at the call-site:
type B[X] = X => X => X
Here are the definitions of true and false, together with a few operations:
def churchTrue[X]: B[X] = a => b => a
def churchFalse[X]: B[X] = a => b => b
def ifThenElse[X](b: B[X], thenResult: X, elseResult: X) =
b(thenResult)(elseResult)
def and[X](a: B[B[X]], b: B[X]): B[X] = a(b)(churchFalse)
def or[X](a: B[B[X]], b: B[X]): B[X] = a(churchTrue)(b)
def not[X](a: B[B[X]]) = a(churchFalse)(churchTrue)
Example:
println("t & t = " + and[String](churchTrue, churchTrue)("t")("f"))
println("t & f = " + and[String](churchTrue, churchFalse)("t")("f"))
println("f & t = " + and[String](churchFalse,churchTrue)("t")("f"))
println("f & f = " + and[String](churchFalse,churchFalse)("t")("f"))
Note that this does not allow you to express the idea of a "Church-Boolean per-se", because it requires a fixed type of the arguments to which it can be applied (String in the above example). As soon as you try to extract the expression from one particular call site and move it elsewhere, you have to readjust all the type parameters, and this is annoying.
Truly polymorphic Church encodings of Booleans
If you want to represent a truly polymorphic function as first-class object, you have to define a trait or abstract class. For booleans, this would be something like
trait B {
def apply[X](trueCase: X, elseCase: X): X
}
Note that now the apply method is polymorphic in X. This allows you to implement Church encodings of Booleans as first-class objects that can be passed around (returned from methods, saved in lists, etc.):
trait B { self =>
def apply[X](thenCase: X, elseCase: X): X
def |(other: B): B = new B {
def apply[A](t: A, e: A) = self(True, other)(t, e)
}
def &(other: B): B = new B {
def apply[A](t: A, e: A) = self(other, False)(t, e)
}
def unary_~ : B = self(False, True)
}
object True extends B { def apply[X](a: X, b: X) = a }
object False extends B { def apply[X](a: X, b: X) = b }
Here is how you can apply it to some actual values:
def toBoolean(b: B): Boolean = b(true, false)
The above line will invoke apply[Boolean](...).
An example:
println("And: ")
println(toBoolean(True & True))
println(toBoolean(True & False))
println(toBoolean(False & True))
println(toBoolean(False & False))
println("Or:")
println(toBoolean(True | True))
println(toBoolean(True | False))
println(toBoolean(False | True))
println(toBoolean(False | False))
println("Funny expresssion that should be `true`:")
println(toBoolean((False | True) & (True & ~False)))
prints:
And:
true
false
false
false
Or:
true
true
true
false
Funny expresssion that should be `true`:
true
Related
The following Haskell code:
main = putStrLn $ "bla " ++ (toStr (A 1) (A 2))
--main2 = putStrLn $ "bla " ++ (toStr (A 1) (A "String")) -- does not compile, as it should
main3 = putStrLn $ "bla " ++ (toStr (A "String") (A "String"))
data A a = A a deriving Show -- (1) data type declaration
class C a where -- (2) type class declaration
toStr :: a-> a->String
instance C (A a) where -- (3) instance declaration
toStr (A x) (A y) = "AA"
corresponds (roughly) to the following Scala code:
case class A[B](b:B) // (1) data type declaration
trait C[A] { // (2) type class declaration
def toStr: A =>A=> String
// this would correspond to "instance C (A a) where"
}
object Instance {
implicit object Instance extends C[A[_]] { // (3) instance declaration
override def toStr: A[_] =>A[_] => String = x => x=> "AA"
// override def toStr[T]: A[T] =>A[T] => String = x => x=> "AA" // this does not override anything, does not compile
}
}
object Main{
println(Instance.Instance.toStr(A(1))(A(2)))
println(Instance.Instance.toStr(A(1))(A("bla"))) // this compiles, but it should not
}
How can I define override def toStr: A[_] =>A[_] => String = x => x=> "AA" such that println(Instance.Instance.toStr(A(1))(A("bla"))) does not compile ?
As it (putStrLn $ "bla " ++ (toStr (A 1) (A "String"))) does not compile in the Haskell code ?
My attempt was override def toStr[T]: A[T] =>A[T] => String = x => x=> "bla" but that does not compile because that does not override def toStr: A =>A=> String
in C.
In summary, how can I translate the above Haskell code to Scala ?
Trying to make instances as objects is not the right approach. It almost always is better to just make anonymous defs that implement the typeclass.
object Instance {
// Corresponds to `instance C (A a)`
implicit def instance[T]: C[A[T]] = new C[A[T]] {
override def toStr: A[T] => A[T] => String = x => y => "AA"
}
}
object Main{
println(Instance.instance.toStr(A(1))(A(2)))
println(Instance.instance.toStr(A(1))(A("bla"))) // doesn't compile
}
So what was wrong with your approach? The root of the problem is that the wildcards _ do not need to be equal - they can individually match different types (recall that _ is just sugar for x forSome { type x }). To get around that, we need to introduce a generic parameter (which is quantified over the whole instance). The natural place to put that is on the object, but this is the second problem: objects don't accept generic parameters.
Why use implicit def
implicit def (with no arguments) is perfect for making type class instances. You can:
introduce type variables as generic parameters on the method (as I did above with B)
introduce superclass constraints as bounds on those generics. For example,
// Corresponds to `instance C a => C (A a)`
implicit def instance[T: C]: C[A[T]] = new C[A[T]] {
override def toStr: A[T] => A[T] => String = x => y => (x,y) match {
case (A(bx),A(by)) => "[" + implicitly[C[T]].toStr(bx)(by) + "]"
}
}
// Corresponds to `instance C String`
implicit val strInstance: C[String] = new C[String] {
override def toStr: String => String => String = x => y => x + y
}
And with that, implicitly[C[A[A[String]]]].toStr(A(A("hi")))(A(A("world"))) returns [[hiworld]].
I want to set a default value to variable. But my Scala compiler says:
Error:(20, 16) unbound placeholder parameter
val p: T = _
^
Here is the code.
object InverseFunctionsExample extends App {
type D = Double
def f(x: D): D = 5 * x + 10
def g(x: D): D = 0.2 * x - 2
printMessage(isInversible(f, g))
def printMessage(inv: Boolean): Unit = {
if (inv) print("YES!") else print("NOPE!")
}
def isInversible[T](f: (T) => T, g: (T) => T): Boolean = {
val p: T = _
if (f(p) == g(p))
true
else
false
}
}
Is it possible to initialize a val p with default value somehow?
Only var fields (not local variables) can be initialized in this way. If you want to define "default values" for different types, the standard approach is the type-class pattern:
case class Default[T](value: T)
object Default {
implicit val defaultInt: Default[Int] = Default(0)
implicit val defaultString: Default[String] = Default("")
...
}
def isInversible[T](f: (T) => T, g: (T) => T)(implicit d: Default[T]): Boolean = {
if (f(d.value) == g(d.value))
true
else
false
// or just f(d.value) == g(d.value)
}
You can use reflection to instantiate a new instance of a class, but that's probably not going to be very useful for you here:
class Foo
classOf[Foo].getConstructor().newInstance()
You can read about the reflection API to see you how you can pick a suitable constructor here.
You could also have a parameter that specifies how to instantiate a new instance:
def isInversible[T](f: T => T, g: T => T, def: => T) = f(def) == g(def)
Since this looks like an inherently math-oriented problem, you might be interested in the Numeric type, which can help facilitate this kind of logic generically for different number types. For example:
def intersectAtOrigin[T](f: T => T, g: T => T)(implicit n: Numeric[T]) = {
val zero = n.zero
f(zero) == g(zero)
}
And then you can do:
def f(x: D): D = 5 * x + 10
def g(x: D): D = 0.2 * x - 2
intersectAtOrigin(f, g) //false, working with Doubles
intersectAtOrigin[Int](_ + 1, x => x * x + x + 1) //true, working with Ints
You can read more about Numeric in the docs here.
You could pass in the value as a parameter of type T
def isInversible[T](f: (T) => T, g: (T) => T)(p: T): Boolean = {
if (f(p) == g(p))
true
else
false
}
An example printMessage(isInversible(f, g)(10))
Given this spinet of code in Scala:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = (d1, d2) => d1 ++ d2
That can be shortened to:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = _ ++ _
What actually the code does is renaming the operator ++ of Map[VertexId, Factor] and therefore: Is there a way to assign that operator to the variable? Like in this imaginary example:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = Map.++
And probably with type inference it would enough to write
val mapMerge = Map[VertexId,Factor].++
Thanks
Unfortunately, no, because the "operators" in Scala are instance methods — not functions from a typeclass, like in Haskell.
Whey you write _ ++ _, you are creating a new 2-argument function(lambda) with unnamed parameters. This is equivalent to (a, b) => a ++ b, which is in turn equivalent to (a, b) => a.++(b), but not to (a, b) => SomeClass.++(a, b).
You can emulate typeclasses by using implicit arguments (see "typeclasses in scala" presentation)
You can pass "operators" like functions — which are not really operators. And you can have operators which look the same. See this example:
object Main {
trait Concat[A] { def ++ (x: A, y: A): A }
implicit object IntConcat extends Concat[Int] {
override def ++ (x: Int, y: Int): Int = (x.toString + y.toString).toInt
}
implicit class ConcatOperators[A: Concat](x: A) {
def ++ (y: A) = implicitly[Concat[A]].++(x, y)
}
def main(args: Array[String]): Unit = {
val a = 1234
val b = 765
val c = a ++ b // Instance method from ConcatOperators — can be used with infix notation like other built-in "operators"
println(c)
val d = highOrderTest(a, b)(IntConcat.++) // 2-argument method from the typeclass instance
println(d)
// both calls to println print "1234765"
}
def highOrderTest[A](x: A, y: A)(fun: (A, A) => A) = fun(x, y)
}
Here we define Concat typeclass and create an implementation for Int and we use operator-like name for the method in typeclass.
Because you can implement a typeclass for any type, you can use such trick with any type — but that would require writing quite some supporting code, and sometimes it is not worth the result.
Suppose I have a list of functions as so:
val funcList = List(func1: A => T, func2: B => T, func2: C => T)
(where func1, et al. are defined elsewhere)
I want to write a method that will take a value and match it to the right function based on exact type (match a: A with func1: A => T) or throw an exception if there is no matching function.
Is there a simple way to do this?
This is similar to what a PartialFunction does, but I am not able to change the list of functions in funcList to PartialFunctions. I am thinking I have to do some kind of implicit conversion of the functions to a special class that knows the types it can handle and is able to pattern match against it (basically promoting those functions to a specialized PartialFunction). However, I can't figure out how to identify the "domain" of each function.
Thank you.
You cannot identify the domain of each function, because they are erased at runtime. Look up erasure if you want more information, but the short of it is that the information you want does not exist.
There are ways around type erasure, and you'll find plenty discussions on Stack Overflow itself. Some of them come down to storing the type information somewhere as a value, so that you can match on that.
Another possible solution is to simply forsake the use of parameterized types (generics in Java parlance) for your own customized types. That is, doing something like:
abstract class F1 extends (A => T)
object F1 {
def apply(f: A => T): F1 = new F1 {
def apply(n: A): T = f(n)
}
}
And so on. Since F1 doesn't have type parameters, you can match on it, and you can create functions of this type easily. Say both A and T are Int, then you could do this, for example:
F1(_ * 2)
The usual answer to work around type erasure is to use the help of manifests. In your case, you can do the following:
abstract class TypedFunc[-A:Manifest,+R:Manifest] extends (A => R) {
val retType: Manifest[_] = manifest[R]
val argType: Manifest[_] = manifest[A]
}
object TypedFunc {
implicit def apply[A:Manifest, R:Manifest]( f: A => R ): TypedFunc[A, R] = {
f match {
case tf: TypedFunc[A, R] => tf
case _ => new TypedFunc[A, R] { final def apply( arg: A ): R = f( arg ) }
}
}
}
def applyFunc[A, R, T >: A : Manifest]( funcs: Traversable[TypedFunc[A,R]] )( arg: T ): R = {
funcs.find{ f => f.argType <:< manifest[T] } match {
case Some( f ) => f( arg.asInstanceOf[A] )
case _ => sys.error("Could not find function with argument matching type " + manifest[T])
}
}
val func1 = { s: String => s.length }
val func2 = { l: Long => l.toInt }
val func3 = { s: Symbol => s.name.length }
val funcList = List(func1: TypedFunc[String,Int], func2: TypedFunc[Long, Int], func3: TypedFunc[Symbol, Int])
Testing in the REPL:
scala> applyFunc( funcList )( 'hello )
res22: Int = 5
scala> applyFunc( funcList )( "azerty" )
res23: Int = 6
scala> applyFunc( funcList )( 123L )
res24: Int = 123
scala> applyFunc( funcList )( 123 )
java.lang.RuntimeException: Could not find function with argument matching type Int
at scala.sys.package$.error(package.scala:27)
at .applyFunc(<console>:27)
at .<init>(<console>:14)
...
I think you're misunderstanding how a List is typed. List takes a single type parameter, which is the type of all the elements of the list. When you write
val funcList = List(func1: A => T, func2: B => T, func2: C => T)
the compiler will infer a type like funcList : List[A with B with C => T].
This means that each function in funcList takes a parameter that is a member of all of A, B, and C.
Apart from this, you can't (directly) match on function types due to type erasure.
What you could instead do is match on a itself, and call the appropriate function for the type:
a match {
case x : A => func1(x)
case x : B => func2(x)
case x : C => func3(x)
case _ => throw new Exception
}
(Of course, A, B, and C must remain distinct after type-erasure.)
If you need it to be dynamic, you're basically using reflection. Unfortunately Scala's reflection facilities are in flux, with version 2.10 released a few weeks ago, so there's less documentation for the current way of doing it; see How do the new Scala TypeTags improve the (deprecated) Manifests?.
Let's assume this function:
def autoClosing(f: {def close();})(t: =>Unit) = {
t
f.close()
}
and this snippet:
val a = autoClosing(new X)(_)
a {
println("before close")
}
is it possible to curry the first part? Something like:
val a = autoClosing(_) { println("before close") }
so that I could send the objects on which close should be performed, and have the same block executed on them?
Yes, the snippet you have given works, as long as you give the type of the placeholder character.
Therefore, the code you are looking for is:
val a = autoClosing(_: {def close();}) { println("before close") }
which compiles and works as expected :).
A couple of notes:
You can make your life easier if you define a type alias for an AnyRef type having a close method, something like type Closeable = AnyRef {def close()}, or an appropriate interface.
The code snippet autoClosing(_: Closeable){ ... } is actually equivalent to the following expanded anonymous function: c: Closeable => autoClosing(c){ ... }. The wildcard character is just shorthand for a partially applied function. You need to give the type of the _ as the type inferer unfortunately cannot infer the type in this case.
Hope it helps,
-- Flaviu Cipcigan
Alternatively you can flip the parameters:
def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1)
In your case:
val a = flip(autoClosing){ println("before close") }
Edit:
I've added some braces to help the human parser:
def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = {
x1 => (x2 => f(x2)(x1))
}
Flip converts a function (A1 => (A2 => B)) to (A2 => (A1 => B)).
scala> def x(x1 : Int)(x2 : Long) = 1.0 * x1 / x2
x: (Int)(Long)Double
scala> val f = flip(x)
f: (Long) => (Int) => Double = <function>
scala> val g = f(1)
g: (Int) => Double = <function>
scala> val h = g(2)
h: Double = 2.0
scala> x(1)(2)
res0: Double = 0.5
I'm happy to see so many people answering Scala questions nowadays. It does make it harder for me to come up with something, however. Here's an alternative to Flaviu's solution.
val a: {def close();} => Unit = autoClosing(_) { println("before close") }
Of course, the proper solution is to define autoClosing in a way compatible with how you are going to use it.