purescript writing implementation for Eq type class - purescript

I wrote this code in purescript
module TypeClasses where
import Prelude
import Data.Array
import Data.Number.Format(toString)
data Point = Point{x:: Number, y:: Number}
instance showPoint :: Show Point where
show (Point {x, y}) = (toString x) <> ", " <> (toString y)
instance eqPoint :: Eq Point where
eq p1 p2 = if (p1.x == p2.x && p1.y1 == p2.y2) then true else false
but I get error
Compiling TypeClasses
Error found:
in module TypeClasses
at src/TypeClasses.purs line 17, column 20 - line 17, column 22
Could not match type
{ x :: t0
| t1
}
with type
Point
while checking that type Point
is at least as general as type { x :: t0
| t1
}
while checking that expression p1
has type { x :: t0
| t1
}
while checking type of property accessor p1.x
in value declaration eqPoint
where t0 is an unknown type
t1 is an unknown type
See https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md for more information,
or to contribute content related to this error.

A couple of issues with your code:
You have to deconstruct the Point parameters to access the "wrapped" record with your actual coordinates like this: eq (Point p1) (Point p2) (this will solve your type error)
.y1 and .y2 do not exist, I guess you mean .y
And as a hint: if something then true else false can be shortened to just something
So you will end up with this implementation of Eq for Point:
instance eqPoint :: Eq Point where
eq (Point p1) (Point p2) = p1.x == p2.x && p1.y == p2.y

Related

API for handling polymothinc records

It is a little bit custom issue, is not contrived, but just simplified as possible.
-- this record that has fn that handles both x and y,
-- x and y supposed to be Functors, a arbitrary param for x/y, r is arbitrary result param
type R0 a x y r =
{ fn :: x a -> y a -> r
}
-- this record that has fn that handles only x
type R1 a x r =
{ fn :: x a -> r
}
What I want is a common API (function) that could handle values of R0 and R1 types.
So I do a sum type
data T a x y r
= T0 (R0 a x y r)
| T1 (R1 a x r)
And I declare this function, there is a constraint that x and y have to be Functors.
some :: ∀ a x y r.
Functor x =>
Functor y =>
T a x y r -> a
some = unsafeCoerce -- just stub
Then try to use it.
data X a = X { x :: a}
data Y a = Y { y :: a }
-- make X type functor
instance functorX :: Functor X where
map fn (X val) = X { x: fn val.x }
-- make Y type functor
instance functorY :: Functor Y where
map fn (Y val) = Y { y: fn val.y }
-- declare functions
fn0 :: ∀ a. X a -> Y a -> Unit
fn0 = unsafeCoerce
fn1 :: ∀ a. X a -> Unit
fn1 = unsafeCoerce
Trying to apply some:
someRes0 = some $ T0 { fn: fn0 } -- works
someRes1 = some $ T1 { fn: fn1 } -- error becase it can not infer Y which should be functor but is not present in f1.
So the question is: Is it possible to make such API work somehow in a sensible/ergonomic way (that would not require some addition type annotations from a user of this API)?
I could apparently implement different functions some0 and some1 for handling both cases, but I wonder if the way with a single function (which makes API surface simpler) is possilbe.
And what would be other suggestions for implementing such requirements(good API handling such polymorphic record types that differ in a way described above, when one of the records has exessive params)?
You should make T1 and T0 separate types and then make function some itself overloaded to work with them both:
data T0 x y r a = T0 (R0 a x y r)
data T1 x r a = T1 (R1 a x r)
class Some t where
some :: forall a. t a -> a
instance someT0 :: (Functor x, Functor y) => Some (T0 x y r) where
some = unsafeCoerce
instance someT1 :: Functor x => Some (T1 x r) where
some = unsafeCoerce
An alternative, though much less elegant, solution would be to have the caller of some explicitly specify the y type with a type signature. This is the default approach in situations when a type can't be inferred by the compiler:
someRes1 :: forall a. a
someRes1 = some (T1 { fn: fn1 } :: T a X Y Unit)
Note that I had to add a type signature for someRes1 in order to have the type variable a in scope. Otherwise I couldn't use it in the type signature T a X Y Unit.
An even more alternative way to specify y would be to introduce a dummy parameter of type FProxy:
some :: ∀ a x y r.
Functor x =>
Functor y =>
FProxy y -> T a x y r -> a
some _ = unsafeCoerce
someRes0 = some FProxy $ T0 { fn: fn0 }
someRes1 = some (FProxy :: FProxy Maybe) $ T1 { fn: fn1 }
This way you don't have to spell out all parameters of T.
I provided the latter two solutions just for context, but I believe the first one is what you're looking for, based on your description of the problem mentioning "polymorphic methods". This is what type classes are for: they introduce ad-hoc polymorphism.
And speaking of "methods": based on this word, I'm guessing those fn functions are coming from some JavaScript library, right? If that's the case, I believe you're doing it wrong. It's bad practice to leak PureScript-land types into JS code. First of all JS code might accidentally corrupt them (e.g. by mutating), and second, PureScript compiler might change internal representations of those types from version to version, which will break your bindings.
A better way is to always specify FFI bindings in terms of primitives (or in terms of types specifically intended for FFI interactions, such as the FnX family), and then have a layer of PureScript functions that transform PureScript-typed parameters to those primitives and pass them to the FFI functions.

Implementing an interface for a plain old recursive data type

I'm fighting with Idris syntax, it seems.
module Test
data Nat = Z | S Nat
Eq Nat where
Z == Z = True
S n1 == S n2 = n1 == n2
_ == _ = False
This complains with the following error (v1.1.1):
.\.\Test.idr:5:8: error: expected: "#",
"with", argument expression,
constraint argument,
function right hand side,
implicit function argument,
with pattern
Eq Nat where
^
Type checking .\.\Test.idr
I don't understand why, I basically used the same syntax as the docs.
When I write an Eq implementation for a custom, non-recursive type, such as Bool, it compiles just fine.
You need to wrap S n patterns in parenthesis. After doing that, your will get compiler errors because Nat is already defined in Prelude. So to compile your code just replace Nat with Natural (or anything else). Though, Z and S constructors are also defined in Prelude so you either need to rename everything to be able to test in REPL easily or use %hide directive.
But at least this code compiles:
module Test
data Natural = Z | S Natural
Eq Natural where
Z == Z = True
(S n1) == (S n2) = n1 == n2
_ == _ = False

Use of the forall construct in Stainless

I'm trying to proof in Stainless that if two lists have the same contents and one list is bounded by x then the other list is also bounded by x. For doing so, I'm told to use the construct:
forall(x => list.content.contains(x) ==> p(x))
The lemma would be written (in a verbose way) as:
def lowerBoundLemma(l1: List[BigInt],l2: List[BigInt],x:BigInt) : Boolean = {
require(l1.content == l2.content && forall(y => l1.content.contains(y) ==> y <= x))
forall(z => l2.content.contains(z) ==> z <= x) because{
forall(z => l2.content.contains(z) ==> z <= x) ==| l1.content == l2.content |
forall(z => l1.content.contains(z) ==> z <= x) ==| trivial |
forall(y => l1.content.contains(z) ==> y <= x)
}
}.holds
The problem is that I get the following errors:
exercise.scala:12:48: error: missing parameter type
require(l1.content == l2.content && forall(y => l1.content.contains(y) ==> y <= x))
Once I add the type to y I get this error (pointing to the left brace of the contains parentheses):
exercise.scala:12:81: error: ')' expected but '(' found.
require(l1.content == l2.content && forall(y : BigInt => l1.content.contains(y) ==> y <= x))
Any idea why this is happening?
I also tried the syntax l.forall(_ <= x) but I get errors when combining with constructs like because and ==| of the type: because is not a member of Boolean.
The issues you are facing are coming from the Scala compiler frontend to Stainless. In Scala, the syntax for a closure (with specified parameter type) is (x: Type) => body (note the extra parentheses!)
If you want to use because and ==|, you'll have to add import stainless.proof._ at the beginning of your source file.

Purescript - Cannot unify type

I am new to Purescript (as well as Haskell) and I am stuck with a cannot unify error.
Initially I had:
newtype Domain = Domain String
newtype Keyword = Keyword String
type Result = {
domain :: Domain,
occurred :: Boolean,
position :: Number,
quality :: Number
}
is_min_pos :: Maybe Result -> Maybe Result -> Maybe Result
is_min_pos Nothing Nothing = Nothing
is_min_pos Nothing y = y
is_min_pos x Nothing = x
is_min_pos x y = if y.position < x.position then y else x
This was giving me the error
Cannot unify type
Prim.Object
with type
Data.Maybe.Maybe
I assumed it was because it was expecting x and y to be of type Maybe Record. So to be explicit I changed the code to, to pattern match by type.
data Result = Result {
domain :: Domain,
occurred :: Boolean,
position :: Number,
quality :: Number
}
is_min_pos (Result x) (Result y) = if y.position < x.position then y else x
Now I get the error
Cannot unify type
Data.Maybe.Maybe Processor.Result
with type
Processor.Result
And this refers to this section
y.position < x.position -- in the first case
and in the second case
Result x -- on the pattern matching side
I am working on it further
type Results = List Result
get_item_with_min_position :: Results -> Maybe Result
--get_item_with_min_position [] = Nothing
get_item_with_min_position results = foldl is_min_pos Nothing results
I am using 'foldl' from Foldable. I am not sure how to pattern match an empty list. If I could, I would change the type signature to
is_min_pos :: Maybe Result -> Result -> Maybe Result
I now get the error
Cannot unify type
Prim.Object
with type
Data.Maybe.Maybe
It is understandable because in
foldl is_min_pos Nothing results
results is of type List Result
is_min_pos expects Maybe Result
What would be a clean way to solve this?
The Maybe type has two data constructors: Nothing, which you are correctly matching, and Just. If you want to match something of type Maybe a which does contain a value, you should match the Just constructor.
You need to modify the final case as follows:
is_min_pos (Just x) (Just y) = if y.position < x.position
then Just y
else Just x
Here, Just x has the type Maybe Result, which is correct according to the type signature, and so x has type Result, so you can use the .position accessor to read its position property.

Precedence of the operators & and | in Scala

In the book "Programming in Scala" (Martin Odersky, 2nd edition) they give this operator precedence table (not complete here):
* / %
+ -
:
= !
< >
&
^
|
So that if the first character of an operator has a higher position in this table that the first character of another operator, the former operator is evaluated first.
According to that this code should print out yy, but it prints out x:
def x() = { print('x'); true }
def y() = { print('y'); true }
x || y && y // prints `x` but should `yy`
My understanding is that if & is higher in the table that |, it must be evaluated first. It is like * has precedence over +, so in x + y * y, the last statement is evalueted first.
EDIT:
Also look at this code
def x() = { print('x'); 1 }
def y() = { print('y'); 3 }
x == x + y * y // xxyy
Look like it evaluates them from left to right but "solves" them according to the table.
Raw version:
x || y && y
With precedence applied:
x || (y && y)
(Note, if the precedence was reversed it would be (x || y) && y.)
Now, you are expecting (y && y) to get evaluated before x, but Scala always evaluates left-to-right (see §6.6 of the language spec). And, as others have mentioned, || is a short-circuiting operator, so the the second operand is not even evaluated if the first operand returns true.
Another way to think of it is as a two method calls, where the second operand of both is pass-by-name:
or (x, and(y, y))
def or(a: Boolean, b: => Boolean): Boolean = if (a) true else b
def and(a: Boolean, b: => Boolean): Boolean = if (!a) false else b
Under the left-to-right evaluation model, x is ALWAYS evaluated first, then maybe y twice.
If you haven't already done so, you could follow Martin Odersky's functional programming course on Coursera where he talks about this very subject in lecture 1 or 2.
Your second example is equivalent to
add(x, mult(y, y))
def add(a: Int, b: Int) = a + b
def mult(a: Int, b: Int) = a * b
x is always evaluated first, then y, twice.
It prints x because x() call returns true and in case of || logic operator if left part return true, the right part is not computed. To compute it use | then, even if left part is true the right part will be evaluated
Updated
Example with boolean is not good, because in case with booleans so called "short-circuit" evaluation is used and scalac won't even look at the second part of or expression if the left part is true. Think of this operation like:
def || (a: => Boolean) = ???