I am trying to see if length of a given list equals some number. However == expects two numbers not Int, so even when I type (==) 1 type is still number -> Bool so finally when I pipe in result of lenght I get compilation error:
-- TYPE MISMATCH ---------------------------------------------------------- REPL
This function cannot handle the argument sent through the (|>) pipe:
4| List.length |> ((==) 1)
^^^^^^
The argument is:
List a -> Int
But (|>) is piping it to a function that expects:
number
Hint: Only Int and Float values work as numbers.
So how can I specify that my constant is an Int as opposed to number variable?
I think you might be overthinking this, checking for equality is as straight forward in Elm as in other languages.
myList = [1, 2, 3]
List.length myList == 3 // True
If you do want to use the (==) function, in case you're doing currying or for other reasons
List.length myList |> (==)
And then you could either store that as a variable or invoke it right away
List.length myList |> (==) 3 // True
OR
lengthChecker = List.length myList |> (==)
lengthChecker 3 // True
But I would say it's better to stick to the simple version of just doing the check with ==.
Just to expand on why your attempt wasn't compiling, the signature for (==) is (==) : a -> a -> Bool meaning it's a function that takes one argument, a, and returns a function that takes one argument, a and returns a Bool. So in your case ((==) 1) is a function that wants a number. When you do List.length |> ((==) 1) you're trying to call that function that expects a number with the List.length function itself.
Use >> to compose functions.
isLengthOne = List.length >> ((==) 1) is a function that checks that the length of a list is 1.
|> pipes the output of one statement to the input of the next.
So aList |> List.length |> ((==) 1) would check aList.
Related
I would like to define overloads of map and min/max (as originally defined in sequtils) that works for tables.keys. Specifically, I want to be able to write something like the following:
import sequtils, sugar, tables
# A mapping from coordinates (x, y) to values.
var locations = initTable[(int, int), int]()
# Put in some random values.
locations[(1, 2)] = 1
locations[(2, 1)] = 2
locations[(-2, 5)] = 3
# Get the minimum X coordinate.
let minX = locations.keys.map(xy => xy[0]).min
echo minX
Now this fails with:
/usercode/in.nim(12, 24) Error: type mismatch: got <iterable[lent (int, int)], proc (xy: GenericParam): untyped>
but expected one of:
proc map[T, S](s: openArray[T]; op: proc (x: T): S {.closure.}): seq[S]
first type mismatch at position: 1
required type for s: openArray[T]
but expression 'keys(locations)' is of type: iterable[lent (int, int)]
expression: map(keys(locations), proc (xy: auto): auto = xy[0])
Below are my three attempts at writing a map that works (code on Nim playground: https://play.nim-lang.org/#ix=3Heq). Attempts 1 & 2 failed and attempt 3 succeeded. Similarly, I implemented min using both attempt 1 & attempt 2, and attempt 1 failed while attempt 2 succeeded.
However, I'm confused as to why the previous attempts fail, and what the best practice is:
Why does attempt 1 fail when the actual return type of the iterators is iterable[T]?
Why does attempt 2 fail for tables.keys? Is tables.keys implemented differently?
Is attempt 2 the canonical way of taking iterators / iterables as function arguments? Are there alternatives to this?
Attempt 1: Function that takes an iterable[T].
Since the Nim manual seems to imply that the result type of calling an iterator is iterable[T], I tried defining map for iterable[T] like this:
iterator map[A, B](iter: iterable[A], fn: A -> B): B =
for x in iter:
yield fn(x)
But it failed with a pretty long and confusing message:
/usercode/in.nim(16, 24) template/generic instantiation of `map` from here
/usercode/in.nim(11, 12) Error: type mismatch: got <iterable[(int, int)]>
but expected one of:
iterator items(a: cstring): char
first type mismatch at position: 1
required type for a: cstring
but expression 'iter' is of type: iterable[(int, int)]
... (more output like this)
From my understanding it seems to say that items is not defined for iterable[T], which seems weird to me because I think items is exactly what's need for an object to be iterable?
Attempt 2: Function that returns an iterator.
I basically copied the implementation in def-/nim-itertools and defined a map function that takes an iterator and returns a new closure iterator:
type Iterable[T] = (iterator: T)
func map[A, B](iter: Iterable[A], fn: A -> B): iterator: B =
(iterator: B =
for x in iter():
yield fn(x))
but this failed with:
/usercode/in.nim(25, 24) Error: type mismatch: got <iterable[lent (int, int)], proc (xy: GenericParam): untyped>
but expected one of:
func map[A, B](iter: Iterable[A]; fn: A -> B): B
first type mismatch at position: 1
required type for iter: Iterable[map.A]
but expression 'keys(locations)' is of type: iterable[lent (int, int)]
proc map[T, S](s: openArray[T]; op: proc (x: T): S {.closure.}): seq[S]
first type mismatch at position: 1
required type for s: openArray[T]
but expression 'keys(locations)' is of type: iterable[lent (int, int)]
expression: map(keys(locations), proc (xy: auto): auto = xy[0])
which hints that maybe tables.keys doesn't return an iterator?
Attempt 3: Rewrite keys using attempt 2.
This replaces tables.keys using a custom myKeys that's implemented in a similar fashion to the version of map in attempt 2. Combined with map in attempt 2, this works:
func myKeys[K, V](table: Table[K, V]): iterator: K =
(iterator: K =
for x in table.keys:
yield x)
Explanation of errors in first attempts
which hints that maybe tables.keys doesn't return an iterator
You are right. It does not return an iterator, it is an iterator that returns elements of the type of your Table keys. Unlike in python3, there seems to be no difference between type(locations.keys) and type(locations.keys()). They both return (int, int).
Here is keys prototype:
iterator keys[A, B](t: Table[A, B]): lent A
The lent keyword avoids copies from the Table elements.
Hence you get a type mismatch for your first and second attempt:
locations.keys.map(xy => xy[0]) has an incorrect first parameter, since you get a (int, int) element where you expect a iterable[A].
Proposals
As for a solution, you can either first convert your keys to a sequence (which is heavy), like hola suggested.
You can directly rewrite a procedure for your specific application, mixing both the copy in the sequence and your operation, gaining a bit in performance.
import tables
# A mapping from coordinates (x, y) to values.
var locations = initTable[(int, int), int]()
# Put in some random values.
locations[(1, 2)] = 1
locations[(2, 1)] = 2
locations[(-2, 5)] = 3
func firstCoordinate[X, Y, V](table: Table[(X, Y), V]): seq[X] =
result = #[]
for x in table.keys:
result.add(x[0])
let minX = locations.firstCoordinate.min
echo minX
This is not strictly adhering your API, but should be more efficient.
How is it possible to correctly manipulate a matrix in Ocaml?
What am I missing here, when assigning a value to a position on the matrix?
let dynamic arraymoedas valor len =
let arrayAux = Array.make_matrix (len+1) (len+1) in
for i=0 to len+1 do
arrayAux.(i).(0)=0;
done;
for j=0 to valor+1 do
arrayAux.(0).(j)= max_int
done;
for i=1 to len+1 do
for j=1 to len+1 do
if(arraymoedas.(i-j) > j) then
arrayAux.(i).(j) = arrayAux.(i - 1).(j)
else
arrayAux.(i).(j) = min (1+arrayAux.(i).(j-arraymoedas.(i - 1))) arrayAux.(i-1).(j)
done;
done;
!arrayAux
Error:
File "Novo_func.ml", line 38, characters 8-16:
38 | arrayAux.(i)(0)=0;
^^^^^^^^
Error: This expression has type 'a -> 'a array array
but an expression was expected of type 'b array
As identified in the comments, there are three issues with the code you've written.
Primarily, you're not using Array.make_matrix properly. This function has type int -> int -> 'a -> 'a array array. You've only supplied the dimensions, but not a default value. When you do this, you get back a function that takes in the default value and returns an array of arrays.
Secondly, when modifying the values in an array, use <- instead of =. Rather than arrayAux.(0).(j) = max_int you want to use arrayAux.(0).(j) <- max_int.
Thirdly, at the end of your dynamic function, you're using the ! operator to deref arrayAux. The problem with this is that arrayAux is not a reference. This will cause a compiler error due to a type mismatch.
I created a generator to generate lists of int with the same lenght and to test the property of zip and unzip.
Running the test I get once in a while the error
Error: System.ArgumentException: list2 is 1 element shorter than list1
but it shouldn't happen because of my generator.
I got three times the test 100% passed and then the error above. Why?
It seems my generator is not working properly.
let samelength (x, y) =
List.length x = List.length y
let arbMyGen2 = Arb.filter samelength Arb.from<int list * int list>
type MyGenZ =
static member genZip() =
{
new Arbitrary<int list * int list>() with
override x.Generator = arbMyGen2 |> Arb.toGen
override x.Shrinker t = Seq.empty
}
let _ = Arb.register<MyGenZ>()
let pro_zip (xs: int list, ys: int list) =
(xs, ys) = List.unzip(List.zip xs ys)
|> Prop.collect (List.length xs = List.length ys)
do Check.Quick pro_zip
Your code, as written, works for me. So I'm not sure what exactly is wrong, but I can give you a few helpful (hopefully!) hints.
In the first instance, try not using the registrating mechanism, but instead using Prop.forAll, as follows:
let pro_zip =
Prop.forAll arbMyGen2 (fun (xs,ys) ->
(xs, ys) = List.unzip(List.zip xs ys)
|> Prop.collect (List.length xs))
do Check.Quick pro_zip
Note I've also changed your Prop.collect call to collect the length of the list(s), which gives somewhat more interesting output. In fact your property already checks that the lists are the same length (albeit implicitly) so the test will fail with a counterexample if they are not.
Arb.filter transforms an existing Arbitrary (i.e. generator and filter) to a new Arbitrary. In other words, arbMyGen2 has a shrinking function that'll work (i.e. only returns smaller pairs of lists that are of equal length), while in genZip() you throw the shrinker away. It would be fine to simply write
type MyGenZ =
static member genZip() = arbMyGen2
instead.
I am trying to use the FsCheck library. I can do some tests but preconditions do not seem to work. The code below provides an example:
let sortEven (xs: int list) =
xs
|> List.filter (fun x -> x % 2 = 0)
|> List.sort
let lengthGT0 (xs: int list) = (List.length xs) > 0
[<Property>]
let checkSortEven (xs: int list) =
lengthGT0 xs ==>
((xs |> sortEven |> List.sum) = (xs |> List.rev |> sortEven |> List.max))
Calling the function checkSortEven with an empty list as its argument generates an exception because List.rev does the same. So, in the code above, I tried to use a precondition, using the ==> operator, to prevent the FsCheck from trying empty lists. However, whether the first list tested is empty or a shrunk list is empty checkSortEven is called an exception is generated:
Falsifiable, after 1 test (0 shrinks) (StdGen (843297067,296354622)):
Original:
[]
with exception:
System.ArgumentException: The input sequence was empty.
Falsifiable, after 1 test (1 shrink) (StdGen (1296284131,296354622)):
Original:
[-1]
Shrunk:
[]
with exception:
System.ArgumentException: The input sequence was empty.
Falsifiable, after 1 test (2 shrinks) (StdGen (1865393009,296354622)):
Original:
[-1; 1]
Shrunk:
[]
with exception:
System.ArgumentException: The input sequence was empty.
There is a related question on SO at Why is my precondition being ignored on my Property-based test? but it seems to be a different case (nested functions).
I also tried Check.QuickThrowOnFailure instead of Check.Quick with basically the same results.
Any ideas on why preconditions are not working in this example?
I attempted to compare a String and String, expecting True.
Idris> String == String
Can't find implementation for Eq Type
Then I expected False when comparing a String to a Bool.
Idris> String /= Bool
Can't find implementation for Eq Type
Am I missing an import?
You can't as it would break parametricity, which we have in Idris. We can't pattern match on types. But this would be necessary to write the Eq implementation, for example:
{- Doesn't work!
eqNat : Type -> Bool
eqNat Nat = True
eqNat _ = False -}
Also, if one could pattern match on types, they would be needed in the run-time. Right now types get erased when compiling.
Just to add some simple examples to the above: types can't be pattern matched on, but there's a two parameter type constructor for propositional equality, described in the documentation section on Theorem Proving. Notice that the only constructor, Refl, makes only values of type (=) x x, where both type parameters are the same. (this is ≡ in Agda)
So this will typecheck:
twoPlusTwoEqFour : 2 + 2 = 4
twoPlusTwoEqFour = Refl
so will this:
stringEqString : String = String
stringEqString = Refl
but not this:
stringEqInt : String = Int
stringEqInt = Refl
-- type error: Type mismatch between String and Int
and this needs extra work to prove, because addition is defined by recursion on the left argument, and n + 0 can't be reduced further:
proof : n = n + 0