Idris - derive extended interface instance - interface

Suppose I have a function f : Ord a => ... which requires a to have and Ord instance.
I can access the Ord a instance using
f : Ord a => ...
f #{ord} ...
Since Eq a => Ord a, a needs to have also an Eq a instance. Is there a way to retrieve it directly from Ord a, instead of doing something like the following?
f : (Eq a, Ord a) => ...
f #{eq} #{ord} ...

It is possible using %implementation, doing something as follows:
eqFromOrd : Ord a => Eq a
eqFromOrd #{ord} = %implementation

I would use the solution by #marcosh, but here is another take on this showing we don't strictly need %implementation:
eqExplicit : Eq a => Eq a
eqExplicit #{eq} = eq
eqFromOrd : Ord a => Eq a
eqFromOrd = eqExplicit

Related

scala: How to convert an anonymous function to val

I'm a beginner learning scala and looking into anon functions and vals.
I'm not able to convert {case e if e % 2 == 0 => e} to a Val. I've tried different syntax (sample shown below) to no avail. There is no real purpose for converting to val; just trying to get a deeper understanding.
package exercises.functions
object CollectVal extends App {
println(List(1,2,3,4,5).collect{case e if e % 2 == 0 => e})
// val onlyEvens: Int = e:Int => Int = e if (e % 2 == 0 ) => e
// val onlyEvens = e:Int = {case e if e % 2 == 0 => e}
println(List(1,2,3,4,5).collect{onlyEvens})
}
Any help is appreciated
Thanks!
What you need to express is a function. So the type of the variable in this case is:
val onlyEvens: Int => Int
In particular, collect accept a PartialFunction (i.e. a function that is not defined for some input value). So it is more correct to write:
val onlyEvens: PartialFunction[Int, Int] = { case e if e % 2 == 0 => e }
Finally, you can pass this val in the collect method:
List(1,2,3,4,5).collect(onlyEvens)
Scastie
Syntax to assign an anonymous function to a val would be something like this (note parentheses around e):
val x: Int => Int = (e) => if (e % 2 == 0) e else ???
or equivalently, but a bit shorter: val x = (e: Int) => if (e % 2 == 0) e else ???
But it looks like what you are looking for is a partial function rather than just a function. PartialFunction is like a regular function, but it is only defined for some of the possible values of its parameter. In your case, you want it only defined for even numbers:
val x = PartialFunction[Int, Int] { case e if e % 2 == 0 => e }
The { case foo => bar } shorthand works for partial functions but not regular functions, that's why you were having problems trying to define a function that way. This creates a PartialFunction that is defined for all integer values that match one of the case clauses, and not for any others.

How do I get the name of the constructor for a product type in purescript?? Similar to haskell conNameOf

I want to extract the value of the constructor for my data which is a sum of product types data X = Xa A | Xb B | Xcd C D | Xefg E F G.... , where A B C... are of the type data A = A {a :: xyz , b :: abc..}
I want a function that gets takes in a value of type X and gives me "Xa", "Xb" .. based on the type. I know I can use case but is there a better way to do this?? Haskell has the toConstr function for this purpose,
I don't think there is a function in the standard library, but if you don't mind using the RTTI mechanisms (which is what conNameOf is using), you can relatively easily make your own using Generic: just convert the value to its generic representation using from, and then extract the constructor by matching on Sum and Constructor:
class ConstrName rep where
constrName' :: rep -> String
instance IsSymbol name => ConstrName (Constructor name a) where
constrName' (Constructor _) = reflectSymbol (Proxy :: Proxy name)
instance (ConstrName a, ConstrName b) => ConstrName (Sum a b) where
constrName' (Inl a) = constrName' a
constrName' (Inr b) = constrName' b
constrName :: forall a rep. Generic a rep => ConstrName rep => a -> String
constrName a = constrName' $ from a
Usage:
> constrName (Xa $ A { a: ..., b: ..., .... })
"Xa"

Instance of Eq with and without Typeclass Constraints

Here is an implementation of Eq for my algebraic data type (ADT)
data Stateful a =
Advancing a
| Stable a
| Finished a
instance statefulEq :: (Eq a) => Eq (Stateful a)
where
eq (Advancing x) (Advancing y) = eq x y
eq (Stable x) (Stable y) = eq x y
eq (Finished x) (Finished y) = eq x y
eq _ _ = false
What this says (I hope) is that Stateful has an instance of Eq if its element has an instance of Eq
Is there a way I can change this to allow for second/backup implementation as well? In SudoCode pseudocode:
instance statefulEq :: Eq (Stateful a)
where
eq (Advancing (Eq x)) (Advancing (Eq y)) = eq x y
eq (Advancing x) (Advancing y) = true
...
A way to say: if the elements have an instance of Eq, use that, otherwise return true.
or if I had some function
isConstrained :: forall a. TypeClass -> a -> Boolean
then perhaps
instance statefulEq :: Eq (Stateful a)
where
eq (Advancing x) (Advancing y)
| isConstrained Eq x && isConstrained Eq x = eq x y
| otherwise = true
...
No, you cannot do this, and there is a good reason for it.
You see, the constraints don't exist universally, they have to be "in scope", which basically means imported from a module in which they're defined.
And this means that the Eq constraint for your type can be either in scope or not, and your program behavior will depend on whether the constraint is in scope. In plainer terms, adding a seemingly unrelated module import may change your program behavior without any warning.
This sort of "action at a distance" is a big enough source of bugs in practice that Haskell and PureScript explicitly disallow it.
Also, a side note: your implementation of Eq (Stateful a) is 100% equivalent to the automatically derived one. You could replace the whole thing with:
derive instance statefulEq :: Eq a => Eq (Stateful a)

Instance of Ord typeclass for option

In volume 4 of Software foundations "QuickChick" we have the following excercise:
Class Ord A `{Eq A} : Type :=
{
le : A -> A -> bool
}.
(* Define [Ord] instances for options and pairs. *)
(* So I am trying to do it *)
Instance optionOrd {A : Type} `{Ord A} `{Eq (option A)} : Ord (option A) :=
{
le := fun (opt1 opt2 : option A) =>
match opt1 with
| None => match opt2 with
| None => true
| Some a => true
end
| Some a1 => match opt2 with
| None => false
| Some a2 => le a1 a2
end
end.
}.
But get an error:
Error: Syntax error: '}' expected after [constr:record_declaration]
(in [vernac:gallina_ext]).
And it highlights match opt1 with.
Maybe, my solution is quite primitive: it just pattern matches all possible cases. Is there anything better?
What causes this syntax error?
Just remove the . after the last end.

Scala filtering on 2 conditions to remove strings from a list

This feels like it should be very simple but after several variations I'm unable to return the correct result.
I have a list of strings that I'm trying to filter on and a Set of strings that I'm using as a blacklist. If any of the strings in my list are in the black list then I want to ignore them and only return the ones that are not present. In addition to this I have another case that I need to check for so I need to make sure its not in the black list and also not condition two.
val strings = List("something", "something.else", "something-else" )
val blacklist = Set(".else", ".new", ".old")
I’m trying to do something like:
strings.filter(f => !f.endsWith("-else"))
to leave just "something" and "something.else" but I can’t seem to return "something" by itself.
strings.filter(
f => !f.endsWith("-else") && !blacklist.exists(suffix => f.endsWith(suffix))
)
Or a shorter (but identical) version:
strings.filter(f => !f.endsWith("-else") && !blacklist.exists(f.endsWith))
I understand you want to remove an element if it ends with something that is in your blacklist.
You could try something like
strings.filter {x => (blacklist map {word => !(x endsWith word)} reduce( (a,b) => a && b ) ) }
with another condition, for example x.length >= 2
strings.filter {x => (blacklist map {word => !(x endsWith word)} reduce( (a,b) => a && b ) ) && x.length >= 2}