How to define a fmap on a record structure with F# - interface

is there a possibility to create an fmap for records so that I can apply the same function to record fields of similar bur different types
Let say I have a record field type Item and a record X and function transform
type Item<'a, 'b> = Item of 'a * 'b
let transform (i: Item<'a, 'b>) : Item<'a, string> =
let (Item (x, y)) = i
Item (x, sprintf "%A" y)
type X<'a> = {
y: Item<'a, int>
z: Item<'a, bool>
}
with
member inline this.fmap(f) =
{
y = f this.y
z = f this.z
}
now the line z = f this.z complains that the given type should be of Item<'a, int> but its of type Item<'a, bool>. Obviously as the type infererrer
has decided that the function f is of type Item<'a, int> -> Item<...> however i want f to be applied polymorphic. How can I get this done?
Evil type hacks are welcome!

An obvious solution is to use bimap instead of fmap and then write twice the function at the caller site:
type Item<'a, 'b> = Item of 'a * 'b
let transform (i: Item<'a, 'b>) : Item<'a, string> =
let (Item (x, y)) = i
Item (x, sprintf "%A" y)
type X<'a> = {
y: Item<'a, int>
z: Item<'a, bool>
}
with
member inline this.bimap(f, g) =
{
y = f this.y
z = g this.z
}
Another alternative (here's the evil type hack) is instead of passing a function, pass what I call an 'Invokable' which some kind of function wrapped in a type with a single method called Invoke. Something like a delegate but static.
Here's an example. I use $ instead of Invoke for simplicity:
let inline fmap invokable ({y = y1; z = z1}) = {y = invokable $ y1; z = invokable $ z1}
type Id = Id with
static member ($) (Id, Item (a,b)) = Item (id a, id b)
type Default = Default with
static member ($) (Default, Item (a:'t,b:'u)) =
Item (Unchecked.defaultof<'t>, Unchecked.defaultof<'u>)
let a = {y = Item ('1', 2); z = Item ('3', true) }
let b = fmap Id a
let c = fmap Default a
Now the problem is I can't think of many other useful functions. Can you?
Otherwise if you make it more generic:
type X<'a, 'b, 'c> = {
y: Item<'a, 'b>
z: Item<'a, 'c>
}
then you can for instance use an Invokable like this:
type ToList = ToList with static member ($) (ToList, Item (a,b)) = Item ([a], [b])
let d = fmap ToList a
// val d : X<char list,int list,bool list> = {y = Item (['1'],[2]);
z = Item (['3'],[true]);}
See also this related question. The case presented there is simpler but the problem is the same.
Also this one is related.

I agree with #Fyodor that using an interface is the cleanest solution if you need to express a polymorphic argument:
type Item<'a, 'b> = Item of 'a * 'b
let transform (i: Item<'a, 'b>) : Item<'a, string> =
let (Item (x, y)) = i
Item (x, sprintf "%A" y)
type ITransform<'a,'x> = abstract Apply : Item<'a,'b> -> Item<'x,'b>
type X<'a> = {
y: Item<'a, int>
z: Item<'a, bool>
}
with
member inline this.fmap(f:ITransform<_,_>) =
{
y = f.Apply this.y
z = f.Apply this.z
}
{ y = Item(1,2); z = Item(3,true) }.fmap
{ new ITransform<_,_> with member __.Apply(Item(i,x)) = Item(i+1, x) }

Related

Boolean logic in lambda calculus in Scala

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

define default named arguments in terms of other arguments in scala

I have a case class that stores three tied parameters. I'd like to define companion object that may build the class from any two parameters, something that looks like the sample below, that is obviously incorrect:
def test(start : Float = end - duration, duration : Float = end - start, end : Float = start + duration) {
require( abs(start + duration - end) < epsilon )
...
}
val t1 = test(start = 0f, duration = 5f)
val t2 = test(end = 4f, duration = 3f)
val t3 = test(start = 3f, end = 5f)
What tricks I may use to get similar usage syntax?
You can use type-classes:
// Represents no argument
object NoArg
// Resolves start, duration, stop
trait DurationRes[A,B,C] {
def resolve(s: A, d: B, e: C): (Float, Float, Float)
}
object DurationRes {
implicit object startEndRes extends DurationRes[Float, NoArg.type, Float] {
def resolve(s: Float, d: NoArg.type, e: Float) = (s, e-s, e)
}
implicit object startDurRes extends DurationRes[Float, Float, NoArg.type] {
def resolve(s: Float, d: Float, e: NoArg.type) = (s, d, s+d)
}
// etc.
}
def test[A,B,C](start: A = NoArg, dur: B = NoArg, end: C = NoArg)
(implicit res: DurationRes[A,B,C]) {
val (s,d,e) = res.resolve(start, dur, end)
// s is start, d duration, e end
}
test(start = 1f, end = 2f)
This way it is even type-safe and you cannot call something like:
test(start = 1f)
or even
test()
After a little thinking I've come with another solution (I don't claim it's better, just would like to know if it's even acceptable approach). The essence is to define a class:
class Klass(val x: Int, val y: Int, val z: Int)
and a companion object:
object Klass {
def apply(x: Int, y: Int)(z: Int = x + y) = {
new Klass(x, y, z)
}
// and so on
}
So you can then do val k = Klass(x = 5, y = 6)() and get val k to refer to Klass(5, 6, 11) instance.
And because of small code amount one can probably define a macros to do the job, but that's a little difficult for me as for now, but is an interesting exercise though.
Update
After some time, I'd like to note to you that there are only three combinations of parameters in your case, so wouldn't it be just easier to provide 3 apply() methods by hand? apply(s, d), apply(s, e), apply(d, e) should suffice your needs. And that will save you some typing, because with other approaches you basically have to code all that cases, too.

Why am I getting "is not a member" here? [duplicate]

This works:
class ButtonCountObserver {
private var cnt = 0 // private field
def count = cnt // reader method
def count_=(newCount: Int) = cnt = newCount // writer method
// ...
}
val b = new ButtonCountObserver
b.count = 0
But this doesn't
class ButtonCountObserver {
private var cnt = 0 // private field
def count_=(newCount: Int) = cnt = newCount // writer method
// ...
}
val b = new ButtonCountObserver
b.count = 0
I get: error: value count is not a member of ButtonCountObserver
Is it possible to create a setter (with the syntactic sugar) without a getter?
The spec requires that both a setter and getter are defined to be able to use the syntactic sugar for calling the setter:
The interpretation of an assignment to
a simple variable x = e depends on the
definition of x. If x denotes a
mutable variable, then the assignment
changes the current value of x to be
the result of evaluating the
expression e. The type of e is
expected to conform to the type of x.
If x is a parameterless function
defined in some template, and the same
template contains a setter function
x_= as member, then the assignment x =
e is interpreted as the invocation
x_=(e ) of that setter function.
Analogously, an assignment f .x = e to
a parameterless function x is
interpreted as the invocation f .x_=(e
). An assignment f (args) = e with a
function application to the left of
the ‘=’ operator is interpreted as f
.update(args, e ), i.e. the invocation
of an update function defined by f .
Furthermore, the getter must be visible in order to use the setter. I'm not sure if this is specified
Getter not visible #1
// error: method x cannot be accessed in x.Test
object x {
class Test {
private[this] var x0: Int = 0
private[Test] def x = x0
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
Getter not visible #2
//<console>:11: error: type mismatch; found : x.Test required: ?{val x: ?}
object x {
class Test {
private[this] var x0: Int = 0
private[this] def x = x0
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
Getter visible
object x {
class Test {
private[this] var x0: Int = 0
private[x] def x = x0
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
As retronym pointed out, there must be a getter present. As a workaround however (if you don't want to provide a getter), you can make the getter return Unit
object x {
class Test {
private[this] var x0: Int = 0
def x: Unit = ()
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
Don't think that that is considered good style (!), but it works.

Perform bridge assignment in scala

I want to do this:
var (a, b) = (0, 0)
a = (b = 100)
but Scala is complaining that
error: type mismatch;
found : Unit
required: Int
What I want is to assign a and b to the same value.
Why Scala make it Unit where it should be Int?
Your statement is an assignment, which returns Unit.
See this related question for reasons why. You can do this, if you want:
scala> var (a,b) = (0,0)
a: Int = 0
b: Int = 0
scala> a = {b = 100; b}
a: Int = 100
scala> var a,b,c,d,e,f,g = 0
a: Int = 0
b: Int = 0
c: Int = 0
d: Int = 0
e: Int = 0
f: Int = 0
g: Int = 0
scala> var f,i,j,k,m,n,o = new Object{}
f: java.lang.Object = $anon$1#11ce012
i: java.lang.Object = $anon$2#baf4ae
j: java.lang.Object = $anon$3#15e68d
k: java.lang.Object = $anon$4#1d3633c
m: java.lang.Object = $anon$5#118317f
n: java.lang.Object = $anon$6#15998cb
o: java.lang.Object = $anon$7#13e6f83
scala>
Why ask why? Assignment expressions have type Unit and that's how it is. No chained assignments. Period.
You can define a special assignment operator (it must end with a colon as it must be right associative) for your own types, or write a generic wrapper (including implit conversions) for general types. I wouldn't recommend to actually use this, but here it goes:
case class M[T](var t:T) {
def =: (m: M[T]):M[T] = {m.t = t ; this}
}
implicit def anyToM[T](v:T) = M(v)
implicit def mToAny[T](m:M[T]) = m.t
def main(args: Array[String]) {
var a = M(0)
var b = M(0)
var c = M(0)
a =: b =: c =: 100
println(a + b + c) //--> 300
}
I think it is always a bad idea to summon heavy magick in order to save a few keystrokes. In Germany we would call this "to shoot sparrows with a cannon"...
case class assign[T](v: T) {
def to(vals: (T => Unit)*) { vals.foreach{ vv => vv(v) } }
}
var (a,b) = (0,0)
assign(39) to (a = _, b = _)
assert(a == 39)
assert(b == 39)
Or you can rename it to emulate a rather simple version of a with statement.
with(20) do (a = _, b = _, print)

Scala: can't write setter without getter?

This works:
class ButtonCountObserver {
private var cnt = 0 // private field
def count = cnt // reader method
def count_=(newCount: Int) = cnt = newCount // writer method
// ...
}
val b = new ButtonCountObserver
b.count = 0
But this doesn't
class ButtonCountObserver {
private var cnt = 0 // private field
def count_=(newCount: Int) = cnt = newCount // writer method
// ...
}
val b = new ButtonCountObserver
b.count = 0
I get: error: value count is not a member of ButtonCountObserver
Is it possible to create a setter (with the syntactic sugar) without a getter?
The spec requires that both a setter and getter are defined to be able to use the syntactic sugar for calling the setter:
The interpretation of an assignment to
a simple variable x = e depends on the
definition of x. If x denotes a
mutable variable, then the assignment
changes the current value of x to be
the result of evaluating the
expression e. The type of e is
expected to conform to the type of x.
If x is a parameterless function
defined in some template, and the same
template contains a setter function
x_= as member, then the assignment x =
e is interpreted as the invocation
x_=(e ) of that setter function.
Analogously, an assignment f .x = e to
a parameterless function x is
interpreted as the invocation f .x_=(e
). An assignment f (args) = e with a
function application to the left of
the ‘=’ operator is interpreted as f
.update(args, e ), i.e. the invocation
of an update function defined by f .
Furthermore, the getter must be visible in order to use the setter. I'm not sure if this is specified
Getter not visible #1
// error: method x cannot be accessed in x.Test
object x {
class Test {
private[this] var x0: Int = 0
private[Test] def x = x0
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
Getter not visible #2
//<console>:11: error: type mismatch; found : x.Test required: ?{val x: ?}
object x {
class Test {
private[this] var x0: Int = 0
private[this] def x = x0
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
Getter visible
object x {
class Test {
private[this] var x0: Int = 0
private[x] def x = x0
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
As retronym pointed out, there must be a getter present. As a workaround however (if you don't want to provide a getter), you can make the getter return Unit
object x {
class Test {
private[this] var x0: Int = 0
def x: Unit = ()
def x_=(a: Int) = x0 = a
}
val t = new Test
t.x = 1
}
Don't think that that is considered good style (!), but it works.