I'm trying to remove duplicate items from already sorted list in OCaml. This is my code:
let rec remove_dup = function
| [] -> []
| hd :: [] -> hd :: []
| hd :: hd2 :: tl -> if (hd == hd2) (remove_dup tl) :: hd else (remove_dup (h2 :: tl) :: hd;;
I'm getting a syntax error.
The OCaml if looks like if expr1 then expr2 else expr3. You're missing the keyword then.
You also have unbalanced parentheses. It looks like you need a right parenthesis at the very end.
After these fixes you have some type errors that you should look at.
As a side comment, don't use == to test for equality. It's a special-purpose operator for advanced uses. The day-to-day equality operator is =.
Related
I was writing a function with user-defined types in OCaml when I encountered an error message that I don't understand.
I'm currently using the OCaml interactive toplevel and also Visual Studio Code to write my code. The strange thing is that when I run the code in Visual Studio Code, it compiles fine but encounters the error in the interactive toplevel.
The OCaml code that I am referring to is as follows:
type loc = int;;
type id = string;;
type value =
| Num of int
| Bool of bool
| Unit
| Record of (id -> loc)
;;
type memory = (loc * value) list;;
exception NotInMemory;;
let rec memory_lookup : (memory * loc) -> value
= fun (mem, l) ->
match mem with
| [] -> raise NotInMemory
| hd :: tl -> (match hd with
| (x, a) -> if x = l then a else (memory_lookup (tl, l))
)
;;
The code that I wrote is basically my rudimentary attempt at implementing/emulating looking up memory and returning corresponding values.
Here's an example input:
memory1 = [ (1, Num 1) ; (2, Bool true) ; (3, Unit) ];;
Here's the expected output:
memory_lookup (memory1, 2);;
- : value = Bool true
However, here's the actual output:
Characters: 179-180:
| (x, a) -> if x = l then "a" else (memory_lookup (tl, l)))
Error: This expression has type value/1076
but an expression was expected of type value/1104
(Just for clarification: the error is regarding character a)
Does anybody know what type value/1076 and type value/1104 mean? Also, if there is anything wrong with the code that I wrote, would anybody be kind enough to point it out?
Thank you.
This kind of error happens in the toplevel when a type is defined multiple times, and some values of the old type are left in scope. A simple example is
type t = A
let x = A;;
type t = A
let y = A;;
x = y;;
Error: This expression has type t/1012 but an expression was expected of type
t/1009
The numerical part after the type name in value/1076 is a binding time for the type value. This binding time is used as a last resort to differentiate between two different types that happens to have the same name. Thus
Error: This expression has type value/1076
but an expression was expected of type value/1104
means that the value memory1 was defined with a type value defined at time 1076, whereas the function memory_lookup expected values of the type value defined at a later date (aka at time 1104). The binding times are a bit arbitrary , so they may be replaced by simply value/1 and value/2 in OCaml 4.08 .
In the Idris Tutorial a function for filtering vectors is based on dependent pairs.
filter : (a -> Bool) -> Vect n a -> (p ** Vect p a)
filter f [] = (_ ** [])
filter f (x :: xs) with (filter f xs )
| (_ ** xs') = if (f x) then (_ ** x :: xs') else (_ ** xs')
But why is it necessary to put this in terms of a dependent pair instead of something more direct such as?
filter' : (a -> Bool) -> Vect n a -> Vect p a
In both cases the type of p must be determined, but in my supposed alternative the redundancy of listing p twice is eliminated.
My naive attempts at implementing filter' failed, so I was wondering is there a fundamental reason that it can't be implemented? Or can filter' be implemented, and perhaps filter was just a poor example to showcase dependent pairs in Idris? But if that is the case then in what situations would dependent pairs be useful?
Thanks!
The difference between filter and filter' is between existential and universal quantification. If (a -> Bool) -> Vect n a -> Vect p a was the correct type for filter, that would mean filter returns a Vector of length p and the caller can specify what p should be.
Kim Stebel's answer is right on the money. Let me just note that this was already discussed on the Idris mailing list back in 2012 (!!):
filter for vector, a question - Idris Programming Language
What raichoo posted there can help clarifying it I think; the real signature of your filter' is
filter' : {p : Nat} -> {n: Nat} -> {a: Type} -> (a -> Bool) -> Vect a n -> Vect a p
from which it should be obvious that this is not what filter should (or even could) do; p actually depends on the predicate and the vector you are filtering, and you can (actually need to) express this using a dependent pair. Note that in the pair (p ** Vect p a), p (and thus Vect p a) implicitly depends on the (unnamed) predicate and vector appearing before it in its signature.
Expanding on this, why a dependent pair? You want to return a vector, but there's no "Vector with unknown length" type; you need a length value for obtaining a Vector type. But then you can just think "OK, I will return a Nat together with a vector with that length". The type of this pair is, unsurprisingly, an example of a dependent pair. In more detail, a dependent pair DPair a P is a type built out of
A type a
A function P: a -> Type
A value of that type DPair a P is a pair of values
x: a
y: P a
At this point I think that is just syntax what might be misleading you. The type p ** Vect p a is DPair Nat (\p => Vect p a); p there is not a parameter for filter or anything like it. All this can be a bit confusing at first; if so, maybe it helps thinking of p ** Vect p a as a substitute for the "Vector with unknown length" type.
Not an answer, but additional context
Idris 1 documentation - https://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#dependent-pairs
Idris 2 documentation - https://idris2.readthedocs.io/en/latest/tutorial/typesfuns.html?highlight=dependent#dependent-pairs
In Idris 2 the dependent pair defined here
and is similar to Exists and Subset but BOTH of it's values are NOT erased at runtime
I want to be able to say, for a function of f with signature t->t, that for all x in t, f(f(x)) = x.
When I run this:
%default total
-- The type of parity values - either Even or Odd
data Parity = Even | Odd
-- Even is the opposite of Odd and Odd is the opposite of Even
opposite: Parity -> Parity
opposite Even = Odd
opposite Odd = Even
-- The 'opposite' function is it's own inverse
opposite_its_own_inverse : (p : Parity) -> opposite (opposite p) = p
opposite_its_own_inverse Even = Refl
opposite_its_own_inverse Odd = Refl
-- abstraction of being one's own inverse
IsItsOwnInverse : {t : Type} -> (f: t->t) -> Type
IsItsOwnInverse {t} f = (x: t) -> f (f x) = x
opposite_IsItsOwnInverse : IsItsOwnInverse {t=Parity} opposite
opposite_IsItsOwnInverse = opposite_its_own_inverse
I get this error message:
- + Errors (1)
`-- own_inverse_example.idr line 22 col 25:
When checking right hand side of opposite_IsItsOwnInverse with expected type
IsItsOwnInverse opposite
Type mismatch between
(p : Parity) ->
opposite (opposite p) = p (Type of opposite_its_own_inverse)
and
(x : Parity) -> opposite (opposite x) = x (Expected type)
Specifically:
Type mismatch between
opposite (opposite v0)
and
opposite (opposite v0)
Am I doing something wrong, or is that just a bug?
If I replace the last 'opposite_its_own_inverse' with '?hole', I get:
Holes
This buffer displays the unsolved holes from the currently-loaded code. Press
the [P] buttons to solve the holes interactively in the prover.
- + Main.hole [P]
`-- opposite : Parity -> Parity
-------------------------------------------------------
Main.hole : (x : Parity) -> opposite (opposite x) = x
The name for this property is an involution. Your type for this property is pretty good but I like writing it like so:
Involution : (t -> t) -> t -> Type
Involution f x = f (f x) = x
The first problem with your opposite_IsItsOwnInverse is that you haven't fully applied Involution so you haven't yet gotten a type. You also need apply a Parity so that Involution gives a Type, like so:
opposite_IsItsOwnInverse : Involution opposite p
That p is an implicit argument. Implicit arguments are implicitly created by lowercase identifiers in type signatures. This is like writing:
opposite_IsItsOwnInverse : {p : Parity} -> Involution opposite p
But this leads to another problem with the signature - opposite is also lowercase, so it's getting treated as an implicit argument! (This is why you get the confusing error message, Idris has created another variable called opposite) You have 2 possible solutions here: qualify the identifier, or use an identifier which starts with an uppercase letter.
I'll assume the module you're writing uses the default name of Main. The final type signature looks like:
opposite_IsItsOwnInverse : Involution Main.opposite p
And the implementation will just use the implicit argument and supply it to the function you've already written:
opposite_IsItsOwnInverse {p} = opposite_its_own_inverse p
In working through Exercise 2 here, I offered this solution to the compiler and got an Infinite Type error.
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: flatten left :: flatten right
This doesn't seem too different from my solution to the first exercise:
sum : Tree Int -> Int
sum tree =
case tree of
Empty -> 0
Node v left right ->
v + sum left + sum right
I wondered if perhaps the issue had to do with order of operations, so I added parens to ensure flatten gets evaluated before ::, but this doesn't seem to make a difference:
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: (flatten left) :: (flatten right)
So now I'm just stumped.
:: is the cons operator, which means it will prepend a single element onto a list. Its type signature is a -> List a -> List a. That means this isn't valid code since the first argument, [v] is a list:
[v] :: flatten left :: flatten right -- invalid!
If you want to concatenate two lists, you use the concatenation operator: ++. You could just replace :: with ++ in your example to get it to compile:
[v] ++ flatten left ++ flatten right
Another way to represent that line is to concatenate the two lists, then prepend the list with v using the cons operator.
v :: flatten left ++ flatten right
-- The following is the same as above, but with parentheses showing precedence
v :: (flatten left ++ flatten right)
There are more efficient ways to do this, of course, but it highlights the difference between cons and concatenation.
The reason your sum example works is because it is returning an int instead of a list of ints. The type you are returning in sum is the same as the value in the tree, so you end up with an aggregate, not another list.
I need an algorithm that converts bin to dec
I found the following code in the Internet , but I just do not know , what some variables mean:
bin2dec :: [Int] -> Int
bin2dec n = foldl (\a x->2*a+x) 0 n
I already know foldl
But what means (\a x->2*a+x) 0 n
I do not know what \a x -> 2*a+x means and also " 0 n"
Could anyone please explain me how this function works ?
Thanks
foldl :: (a -> b -> a) -> a -> [b] -> a
So basically a is first 0 and then the value that is carried throughout the fold. n is the list you pass into bin2dec and 0 is the object you start your fold on.
\a x -> 2 * a + x is a lamda function. It takes two variables, a and x and returns the value given on the right side of the arrow.