Extending existing Record type - purescript

If I have a record type:
type Rec_ab = { a :: String, b :: Int }
Can I get from it type which is effectfully extended with {c :: Boolean} : { a :: String, b :: Int, c :: Boolean }?
If I had a row, I could do it:
Row_ab = ( a :: String, b :: Int )
Rec_abc = { c :: Boolean | Row_ab }
but if I have a record Rec_ab how this should be solved? I'm not aware of the way of going from Record -> Row.

In general, you can't.
If you need that kind of extensibility, your approach with Row_ab is good enough, but another possible solution is to parametrize the record and then use the parameter to extend it:
type Rec_ab r = { a :: String, b :: Int | r }
type Rec_abc = Rec_ab ( c :: Boolean )
This also allows you to write functions that would work with both Rec_ab and Rec_abc:
add42 :: forall r. Rec_ab r -> Rec_ab r
add42 r = r { b = r.b + 42 }

Related

How to have row without particular field as function param

What I want is following, I have a row type:
type FooBarBaz =
( foo :: Int
, bar :: String
, baz :: Boolean
)
Then a need a function that takes this row type record but without "foo": and adds default "foo" field:
withoutFoo { bar: "bar", baz: true} -- > { foo: 1, bar: "bar", baz: true}
I tried to do something like this, but can not get it around:
withoutFoo :: ∀ r.
Lacks "foo" r =>
Cons "foo" Int r FooBarBaz =>
{ | r } -> { | FooBarBaz }
withoutFoo props = Record.union { foo: 1 } props
UPD:
managed to solve it with Union constraint:
withoutFoo :: ∀ r.
Union r ( foo :: Int ) FooBarBaz =>
{ | r } -> { | FooBarBaz }
withoutFoo props =
Record.merge props { foo: 1 }
The problem is that your function isn't actually generic. There is only one possible choice for r: it should always be (bar :: String, baz :: Boolean)
So just make that the type of your function:
withoutFoo :: { bar :: String, baz :: Boolean } -> { | FooBarBaz }
withoutFoo props = Record.union { foo: 1 } props

scodec decode/encode split length field

I am using scodec: https://github.com/scodec/scodec to decode/encode a binary protocol.
I am struggling with a part of the spec where a "length" field is split into two parts by a "moreflag". The moreflag indicates if the length field needs more space.
Example:
Byte 1: identifier bits 8-7, moreFlag bit 6, length bits 5-0 // first length field filled with 0's if moreFlag is false
Byte 2: moreFlag bit 8, length bits 7-0
Byte 3: otherJunk bits 8-0
My problem is I want to encode/decode both of these length fields into a single case class field:
case class Header(totalLength: Int, otherJunk: Int)
I have tried a few different things, but nothing has worked out so far:
implicit val headerCodec: Codec[Header] = (
("identifier" | uint2) :~>:
("moreFlag" | bool).compact >>:~ { meta =>
if (meta.last) {
// more flag enabled, combine lengths somehow
("first length part" | uint(5)) :: ("moreFlag2DontCare" | uint(1) :~>: ("second length part - how to combine?" | uint(7)) :: ("otherJunk" | uint8)
}
else {
("first length part always 0s" | constant(bin"00000")) :: ("moreFlag2DontCare" | uint(1) :~>: ("fullLength" | uint(7)) :: ("otherJunk" | uint8)
}
}
).as[Header]
Am I on the right track here? Thanks!
One way to accomplish this is to use the predefined combinators to define the structure of the binary format -- not the combination logic. Then put the combination logic inside a function passed to xmap.
import scodec._
import bits._
import codecs._
import shapeless._
case class Header(totalLength: Int, otherJunk: Int)
object Header {
implicit val codec: Codec[Header] = {
type Struct = Int :: Boolean :: BitVector :: Boolean :: BitVector :: Int :: HNil
val struct: Codec[Struct] = ("identifier" | uint2) :: ("moreFlag" | bool) :: ("upper length bits" | codecs.bits(5)) :: ("moreFlag2" | bool) :: ("lower length bits" | codecs.bits(7)) :: ("other junk" | uint8)
def to(header: Header): Struct = {
val lengthBits = uint(12).encodeValid(header.totalLength)
val more = !(lengthBits startsWith bin"00000")
0 :: more :: lengthBits.take(5) :: false :: lengthBits.drop(5) :: header.otherJunk :: HNil
}
def from(struct: Struct): Header = struct match {
case id :: moreFlag :: upperLengthBits :: moreFlag2 :: lowerLengthBits :: otherJunk :: HNil =>
val length =
if (moreFlag) uint(12).decodeValidValue(upperLengthBits ++ lowerLengthBits)
else uint(7).decodeValidValue(lowerLengthBits)
Header(length, otherJunk)
}
struct.xmap[Header](from, to)
}
}
Note that the upper and lower length bits are encoded as bits(5) and bits(7) and then manually combined in the from function and decoded. The decoding is safe, despite using the unsafe decodeValidValue, because the uint(12) codec is total on 12-bit inputs -- it is impossible for it to return a left.
However, the to function uses encodeValid, which is clearly unsafe -- e.g., Int.MaxValue will cause an exception. We can fix this with a slightly more complicated version, where the to function returns an Err \/ Struct, and we call widen instead of xmap:
object Header {
implicit val codec: Codec[Header] = {
type Struct = Int :: Boolean :: BitVector :: Boolean :: BitVector :: Int :: HNil
val struct: Codec[Struct] = ("identifier" | uint2) :: ("moreFlag" | bool) :: ("upper length bits" | codecs.bits(5)) :: ("moreFlag2" | bool) :: ("lower length bits" | codecs.bits(7)) :: ("other junk" | uint8)
def to(header: Header): Err \/ Struct = {
uint(12).encode(header.totalLength) map { lengthBits =>
val more = !(lengthBits startsWith bin"00000")
0 :: more :: lengthBits.take(5) :: false :: lengthBits.drop(5) :: header.otherJunk :: HNil
}
}
def from(struct: Struct): Header = struct match {
case id :: moreFlag :: upperLengthBits :: moreFlag2 :: lowerLengthBits :: otherJunk :: HNil =>
val length =
if (moreFlag) uint(12).decodeValidValue(upperLengthBits ++ lowerLengthBits)
else uint(7).decodeValidValue(lowerLengthBits)
Header(length, otherJunk)
}
struct.widen[Header](from, to)
}
}

How to use HList to validate input?

I'm using Shapeless 2.0 and I'm trying to use HList to validate input — with as much of the checking as possible performed at compile time.
I have an HList spec that specifies what type of input I'm expecting (the types should be checked at compile time) and may also include a runtime check to be performed (e.g., to test if a number is even or odd).
Consider the following specification:
trait Pred[T] { def apply(t: T): Boolean }
val IsString = new Pred[String] { def apply(s: String) = true }
val IsOddNumber = new Pred[Int] { def apply(n: Int) = n % 2 != 0 }
val IsEvenNumber = new Pred[Int] { def apply(n: Int) = n % 2 == 0 }
val spec = IsEvenNumber :: IsString :: IsString :: IsOddNumber :: HNil
And various sample inputs:
val goodInput = 4 :: "foo" :: "" :: 5 :: HNil
val badInput = 4 :: "foo" :: "" :: 4 :: HNil
val malformedInput = 4 :: 5 :: "" :: 6 :: HNil
How would I make a function where I can effectively do:
input.zip(spec).forall{case (input, test) => test(input)}
So the following would happen:
f(spec, goodInput) // true
f(spec, badInput) // false
f(spec, malformedInput) // Does not compile
These answers by Travis Brown include most of what's needed:
https://stackoverflow.com/a/20452151/86485
https://stackoverflow.com/a/21005225/86485
but it took me a long time to find those answers, figure out that they were applicable to your problem, and work out the details of combining and applying them.
And I think your question adds value because it demonstrates how this can come up when solving a practical problem, namely validating input. I'll also try to add value below by showing a complete solution including demo code and tests.
Here's generic code for doing the checking:
object Checker {
import shapeless._, poly._, ops.hlist._
object check extends Poly1 {
implicit def apply[T] = at[(T, Pred[T])]{
case (t, pred) => pred(t)
}
}
def apply[L1 <: HList, L2 <: HList, N <: Nat, Z <: HList, M <: HList](input: L1, spec: L2)(
implicit zipper: Zip.Aux[L1 :: L2 :: HNil, Z],
mapper: Mapper.Aux[check.type, Z, M],
length1: Length.Aux[L1, N],
length2: Length.Aux[L2, N],
toList: ToList[M, Boolean]) =
input.zip(spec)
.map(check)
.toList
.forall(Predef.identity)
}
And here's the demo usage code:
object Frank {
import shapeless._, nat._
def main(args: Array[String]) {
val IsString = new Pred[String] { def apply(s: String) = true }
val IsOddNumber = new Pred[Int] { def apply(n: Int) = n % 2 != 0 }
val IsEvenNumber = new Pred[Int] { def apply(n: Int) = n % 2 == 0 }
val spec = IsEvenNumber :: IsString :: IsString :: IsOddNumber :: HNil
val goodInput = 4 :: "foo" :: "" :: 5 :: HNil
val badInput = 4 :: "foo" :: "" :: 4 :: HNil
val malformedInput1 = 4 :: 5 :: "" :: 6 :: HNil
val malformedInput2 = 4 :: "foo" :: "" :: HNil
val malformedInput3 = 4 :: "foo" :: "" :: 5 :: 6 :: HNil
println(Checker(goodInput, spec))
println(Checker(badInput, spec))
import shapeless.test.illTyped
illTyped("Checker(malformedInput1, spec)")
illTyped("Checker(malformedInput2, spec)")
illTyped("Checker(malformedInput3, spec)")
}
}
/*
results when run:
[info] Running Frank
true
false
*/
Note the use of illTyped to verify that code that should not compile, does not.
Some side notes:
I initially went down a long garden path with this, where I thought it would be important for the polymorphic function check to have a more specific type than Poly1, to represent that the return type in all cases is Boolean. So I kept trying to make it work with extends (Id ~>> Boolean). But it turns out not to matter whether the type system knows that the result type is the Boolean in every case. It's enough that the only case that we actually have has the right type. extends Poly1 is a marvelous thing.
Value-level zip traditionally allows unequal lengths and discards the extras. Miles followed suit in Shapeless's type-level zip, so we need a separate check for equal lengths.
It's a bit sad that the call site has to import nat._, otherwise the implicit instances for Length aren't found. One would prefer these details to be handled at the definition site. (A fix is pending.)
If I understand correctly, I can't use Mapped (a la https://stackoverflow.com/a/21005225/86485) to avoid the length check, because some of my checkers (e.g. IsString) have singleton types that are more specific than just e.g. Pred[String].
Travis points out that Pred could extend T => Boolean, making it possible to use ZipApply. I leave following this suggestion as an exercise for the reader :-)

Scala function transformation

Say I've got a function taking one argument
def fun(x: Int) = x
Based on that, I want to generate a new function with the same calling convention, but that'll apply some transformation to its arguments before delegating to the original function. For that, I could
def wrap_fun(f: (Int) => Int) = (x: Int) => f(x * 2)
wrap_fun(fun)(2) // 4
How might one go about doing the same thing, except to functions of any arity that only have the part of the arguments to apply the transformation to in common?
def fun1(x: Int, y: Int) = x
def fun2(x: Int, foo: Map[Int,Str], bar: Seq[Seq[Int]]) = x
wrap_fun(fun1)(2, 4) // 4
wrap_fun(fun2)(2, Map(), Seq()) // 4
How would a wrap_fun definition making the above invocations work look like?
This can be done in fairly straightforwardly using shapeless's facilities for abstracting over function arity,
import shapeless._
import HList._
import Functions._
def wrap_fun[F, T <: HList, R](f : F)
(implicit
hl : FnHListerAux[F, (Int :: T) => R],
unhl : FnUnHListerAux[(Int :: T) => R, F]) =
((x : Int :: T) => f.hlisted(x.head*2 :: x.tail)).unhlisted
val f1 = wrap_fun(fun _)
val f2 = wrap_fun(fun1 _)
val f3 = wrap_fun(fun2 _)
Sample REPL session,
scala> f1(2)
res0: Int = 4
scala> f2(2, 4)
res1: Int = 4
scala> f3(2, Map(), Seq())
res2: Int = 4
Note that you can't apply the wrapped function immediately (as in the question) rather than via an assigned val (as I've done above) because the explicit argument list of the wrapped function will be confused with the implicit argument list of wrap_fun. The closest we can get to the form in the question is to explicitly name the apply method as below,
scala> wrap_fun(fun _).apply(2)
res3: Int = 4
scala> wrap_fun(fun1 _).apply(2, 4)
res4: Int = 4
scala> wrap_fun(fun2 _).apply(2, Map(), Seq())
res5: Int = 4
Here the explicit mention of apply syntactically marks off the first application (of wrap_fun along with its implicit argument list) from the second application (of the transformed function with its explicit argument list).
As usual in Scala, there's yet another way to achieve what you want to do.
Here is a take based on currying of the first argument together with the compose of Function1:
def fun1(x : Int)(y : Int) = x
def fun2(x : Int)(foo : Map[Int, String], bar : Seq[Seq[Int]]) = x
def modify(x : Int) = 2*x
The resulting types as REPL shows you will be:
fun1: (x: Int)(y: Int)Int
fun2: (x: Int)(foo: Map[Int,String], bar: Seq[Seq[Int]])Int
modify: (x: Int)Int
And instead of wrapping the functions fun1 and fun2, you compose them, as technically, they are now both Function1 objects. This allows you to make calls like the following:
(fun1 _ compose modify)(2)(5)
(fun2 _ compose modify)(2)(Map(), Seq())
Both of which will return 4. Granted, the syntax is not that nice, given that you have to add the _ to distinguish fun1's application from the function object itself (on which you want to call the compose method in this case).
So Luigi's argument that it is impossible in general remains valid, but if you are free to curry your functions you can do it in this nice way.
Since functions taking different numbers of arguments are different, unrelated types, you cannot do this generically. trait Function1 [-T1, +R] extends AnyRef and nothing else. You will need a separate method for each arity.
While I voted for and agree with Luigi's answer–because, you know... he's right; Scala doesn't have direct, in-built support for such a thing–it's worth noting that what you're trying to do isn't impossible; it's just that it's a bit of a pain to pull off, and, often times, you're best off just implementing a separate method per desired arity.
That said, though... we can actually do this HLists. If you're interested in trying it out, naturally, you'll need to obtain an HList implementation. I recommend utilizing Miles Sabin's excellent shapeless project and its implementation of HLists. Anyway, here's an example of its use that accomplishes something akin to what you seem to be looking for:
import shapeless._
trait WrapperFunner[T] {
type Inputs <: HList
def wrapFun(inputs: Inputs) : T
}
class WrapsOne extends WrapperFunner[Int] {
type Inputs = Int :: HNil
def wrapFun(inputs: Inputs) : Int = {
inputs match {
case num :: HNil => num * 2
}
}
}
class WrapsThree extends WrapperFunner[String] {
type Inputs = Int :: Int :: String :: HNil
def wrapFun(inputs: Inputs) : String = {
inputs match {
case firstNum :: secondNum :: str :: HNil => str + (firstNum - secondNum)
}
}
}
object MyApp extends App {
val wo = new WrapsOne
println(wo.wrapFun(1 :: HNil))
println(wo.wrapFun(17 :: HNil))
//println(wo.wrapFun(18 :: 13 :: HNil)) // Would give type error
val wt = new WrapsThree
println(wt.wrapFun(5 :: 1 :: "your result is: " :: HNil))
val (first, second) = (60, 50)
println(wt.wrapFun(first :: second :: "%s minus %s is: ".format(first, second) :: HNil))
//println(wt.wrapFun(1 :: HNil)) // Would give type error
}
Running MyApp results in:
2
34
your result is: 4
60 minus 50 is: 10
Or, extended closer to your particular case:
import shapeless._
trait WrapperFunner[T] {
type Inputs <: HList
def wrapFun(inputs: Inputs) : T
}
trait WrapperFunnerBase extends WrapperFunner[Int] {
// Does not override `Inputs`
def wrapFun(inputs: Inputs) : Int = {
inputs match {
case (num: Int) :: remainder => num
}
}
}
class IgnoresNothing extends WrapperFunnerBase {
type Inputs = Int :: HNil
}
class IgnoresLastTwo extends WrapperFunnerBase {
type Inputs = Int :: Int :: String :: HNil
}
object MyApp extends App {
val in = new IgnoresNothing
println(in.wrapFun(1 :: HNil))
println(in.wrapFun(2 :: HNil))
//println(in.wrapFun(3 :: 4 :: HNil)) // Would give type error
val ilt = new IgnoresLastTwo
println(ilt.wrapFun(60 :: 13 :: "stupid string" :: HNil))
println(ilt.wrapFun(43 :: 7 :: "man, that string was stupid..." :: HNil))
//println(ilt.wrapFun(1 :: HNil)) // Would give type error
}
results in:
1
2
60
43

Ternary Operator Similar To ?:

I am trying to avoid constructs like this:
val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result
Ok, in this example the then and else branch are simple, but you can image complex ones.
I built the following:
object TernaryOp {
class Ternary[T](t: T) {
def is[R](bte: BranchThenElse[T,R]) = if (bte.branch(t)) bte.then(t) else bte.elze(t)
}
class Branch[T](branch: T => Boolean) {
def ?[R] (then: T => R) = new BranchThen(branch,then)
}
class BranchThen[T,R](val branch: T => Boolean, val then: T => R)
class Elze[T,R](elze: T => R) {
def :: (bt: BranchThen[T,R]) = new BranchThenElse(bt.branch,bt.then,elze)
}
class BranchThenElse[T,R](val branch: T => Boolean, val then: T => R, val elze: T => R)
implicit def any2Ternary[T](t: T) = new Ternary(t)
implicit def fct2Branch[T](branch: T => Boolean) = new Branch(branch)
implicit def fct2Elze[T,R](elze: T => R) = new Elze(elze)
}
Defined that, I can replace the above simple example with:
this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}
But how can I get rid of the s: String =>? I want something like that:
this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}
I guess the compiler needs the extra stuff to infer types.
From Tony Morris' Lambda Blog:
I hear this question a lot. Yes it does. Instead of c ? p : q, it is
written if(c) p else q.
This may not be preferable. Perhaps you’d like to write it using the
same syntax as Java. Sadly, you can’t. This is because : is not a
valid identifier. Fear not, | is! Would you settle for this?
c ? p | q
Then you’ll need the following code. Notice the call-by-name (=>)
annotations on the arguments. This evaluation strategy is required to
correctly rewrite Java’s ternary operator. This cannot be done in Java
itself.
case class Bool(b: Boolean) {
def ?[X](t: => X) = new {
def |(f: => X) = if(b) t else f
}
}
object Bool {
implicit def BooleanBool(b: Boolean) = Bool(b)
}
Here is an example using the new operator that we just defined:
object T { val condition = true
import Bool._
// yay!
val x = condition ? "yes" | "no"
}
Have fun ;)
We can combine How to define a ternary operator in Scala which preserves leading tokens? with the answer to Is Option wrapping a value a good pattern? to get
scala> "Hi".getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res0: String = String
scala> List.getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res1: String = List
Is this adequate for your needs?
Rex Kerr’s answer expressed in basic Scala:
"Hi".getClass.getSimpleName match {
case x if x.endsWith("$") => x.init
case x => x
}
although I’m not sure what part of the if–else construct you want to optimise.
Since if-else constructions in Scala return a value, you can use this
val a = if (1 < 0) 1 else 2
More info: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples
Since : by itself won't be a valid operator unless you are ok with always escaping it with back ticks :, you could go with another character, e.g. "|" as in one of the answers above. But how about elvis with a goatee ?::
implicit class Question[T](predicate: => Boolean) {
def ?(left: => T) = predicate -> left
}
implicit class Colon[R](right: => R) {
def ::[L <% R](pair: (Boolean, L)): R = if (q._1) q._2 else right
}
val x = (5 % 2 == 0) ? 5 :: 4.5
Of course this again won't work if you values are lists, since they have :: operator themselves.