How to create an empty list in Idris REPL? - list

I want to create myEmptyList and myNonemptyList in REPL. However Idris reported a type mismatch error for myEmptyList. Why?
____ __ _
/ _/___/ /____(_)____
/ // __ / ___/ / ___/ Version 1.3.0
_/ // /_/ / / / (__ ) http://www.idris-lang.org/
/___/\__,_/_/ /_/____/ Type :? for help
Idris is free software with ABSOLUTELY NO WARRANTY.
For details type :warranty.
Idris> :let myEmptyList : List Integer = []
(input):1:33: When checking type of myEmptyList:
When checking argument y to type constructor =:
Type mismatch between
List elem (Type of [])
and
Type (Expected type)
(input):1:18:No type declaration for myEmptyList
Idris> :let myNonemptyList : List Integer = [42]

The mismatch is because :let myEmptyList : List Integer = [] does not define myEmptyList, it only declares its type as List Integer = [], an equality type, which is ill-typed because [] and List Integer have different types.
You can define myEmptyList as follows: :let myEmptyList : List Integer; myEmptyList = [], or alternatively :let myEmptyList = the (List Integer) [].

Related

How to show integers in a String through recursion

I am new to Haskell and I am running into some problems with my recursive solution. I would appreciate any and all help!
My first goal was to create a function that would check the order of the string of "A", "B" and "C" and to output an integer array mapping each of these to a number via recursion.
My second goal was to create a function that would take two integer arrays (one of them would be the integer array created from check_order (consisting of 1, 2, and 3) and one would be a random integer array of length 3) and return a string such that 1 would be replaced by the first element of the random integer array, 2 would be replaced by the second element of the random integer array, etc.
Here is my code:
-- Takes any String consisting of namely A, B, and C and returns an Integer
-- with 1, 2, and 3 that corresponds to each particular character.
check_order :: String -> [Int]
check_order "" = []
check_order (x:xs)
| x `elem` "A" = 1 : check_order xs
| x `elem` "B" = 2 : check_order xs
| otherwise = 3 : check_order xs
-- Takes the integer array generated from check_order and an arbitrary
-- integer array of length 3 and returns a String correlating the check_order
-- array and the arbitrary integer array
number_correction :: Integral n => [n] -> [n] -> String
number_correction [] _ = ""
number_correction (x:xs) num_array
| x == 1 = show (num_array !! 0) ++ " " ++ number_correction xs num_array
| x == 2 = show (num_array !! 1) ++ " " ++ number_correction xs num_array
| otherwise = show (num_array !! 2) ++ " " ++ number_correction xs num_array
main = do
let test = "ABCBABBAC";
let num_array = [6, 1, 8];
print(number_correction(check_order(test), num_array));
--This print statement should print out "6 1 8 1 6 1 1 6 8"
Here are the error logs:
[1 of 1] Compiling Main ( main.hs, main.o )
main.hs:12:16: error:• Could not deduce(Show n) arising from a use of ‘show’
from the context: Integral n
bound by the type signature for:number_correction :: Integral n => [n] -> [n] -> String
at main.hs:9:1-55
Possible fix:add (Show n) to the context of
the type signature for:
number_correction :: Integral n => [n] -> [n] -> String
• In the firstargument of ‘(++)’, namely ‘show (num_array !! 0)’
In the expression:
show (num_array !! 0) ++ " " ++ number_correction xs num_array
In anequation for ‘number_correction’:
number_correction (x : xs) num_array
| x == 1
=show (num_array !! 0) ++ " " ++ number_correction xs num_array
| x == 2
= show (num_array !! 1) ++ " " ++ number_correction xs num_array
| otherwise
= show (num_array !! 2) ++ " " ++ number_correction xs num_array
main.hs:19:31: error:
• Couldn't match expected type ‘[n0]’
with actual type ‘([Int], [Integer])’
• In the first argument of ‘number_correction’, namely
‘(check_order (test), num_array)’
In the first argument of ‘print’, namely
‘(number_correction (check_order (test), num_array))’
In a stmt of a'do' block:
print (number_correction (check_order (test), num_array))
(Int n) => [n] -> [n] -> String doesn't make any sense. Int is a concrete type, so what is Int n supposed to mean? It's like writing
foo = True 37
– you're trying to use something as a function that's not a function.
What you probably had in mind is the admittedly very similar-looking
number_correction :: Integral n => [n] -> [n] -> String
Unlike Int, Integral is a type class. Unlike in Java, types and classes in Haskell are completely different beasts. In particular, Integral is a function on the type level. You can see this in GHCi:
Prelude> :k Int
Int :: Type
Prelude> :k Integral
Integral :: Type -> Constraint
(traditionally it would show * and * -> Constraint, with * being the old symbol denoting the kind of types).
So, Integral n does make sense: you apply the Type -> Constraint to a variable n of kind Type, and thus get a constraint. Constraints are what can appear on the LHS of the => arrow.
You could also make a constraint with Int. That requires the (common enough) -XTypeFamilies extension, then you can write
number_correction :: (n ~ Int) => [n] -> [n] -> String
In this case you basically use the “class of all types which are equal to Int”, which is a bit silly. The Integral class contains the type Int, but also other types such as Integer and Int32.
If you really want to allow only Int, you should simply write
number_correction :: [Int] -> [Int] -> String

Int lists in functions

Does this function take two int lists "x and y" and return an int list of y-x?
let rec fun4 (l: int list) :int list =
begin match l with | [] -> []
| [_] -> []
| x::y::rest -> (y-x)::(fun4 (y::rest))
end
A list is defined as a recursive type:
type 'a list =
| [] of 'a list (* the empty case *)
| ( :: ) of 'a * 'a list
So you basically have two constructors: [] which is the empty list, and x :: other_list which is a list with x as head and other_list as tail. The use of these constructors makes it easy to define a list: [0; 1; 2; 3] is exactly the same of 0 :: 1 :: 2 :: 3 and of (::) (0, (::) (1, (::) (2, (::) (3, [])))) (which is not very pleasant to read).
Recursive algebraic types, here we have the conjunction of sums ([] and (::)) and products (('a * 'a list)), combined with pattern matching make it possible to describe all sorts of common data structures, as well as their functions for consuming, modifying etc.
In your example, you use pattern matching to deconstruct the list:
let rec fun4 my_list =
match my_list with
(* if my list is empty, I can't process the function so
I return the empty list *)
| [] -> []
(* if my list my list has only one element, I can't process the function
so, like in the previouse case, I return the empty list *)
| [ _ ] -> []
(* Here is the last case of the function, If I almost have two elements in the
list. Remember that empty list is also a list ! *)
| x :: y :: rest -> (y - x) :: (fun4 (y :: rest))
As you can see, Recursives Algebraic data types coupled with pattern matching are a powerful for describing data structures (like list but also many others) and for writing function that use those data structures.

operator and operand do not agree [tycon mismatch]

I am trying to write a function in sml that takes in a list of pairs and returns pair of two list of all the elements
Meaning if the input is [(1, 2.0), (2, 3.0)]
The output should be ([1, 2], (2.0, 3.0))
fun divide nil = (nil , nil)
| divide [(a, b)::nil] = ([a], [b])
| divide [(a, b)::myTl] =
let
val (x, y) = divide myTl
in
(a::x, b::y)
end
;
Never the less the sml interpreter returns the following err
Error: operator and operand do not agree [tycon mismatch]
operator domain: ('Z * 'Y) list list
operand: ('Z * 'Y) list
in expression:
divide myTl
The error message you're seeing is because you've (inadvertently) declared a function with domain ('a * 'b) list list due to your input patterns, so your recursive call is not well typed.
The most straightforward fix is to correct for the incorrect use of [ ] around the argument to the function---this is making a singleton list, instead of just grouping the pattern. Thus you'd want to use ( ) instead.
fun divide nil = (nil , nil)
| divide ((a, b)::nil) = ([a], [b])
| divide ((a, b)::myTl) =
let
val (x, y) = divide myTl
in
(a::x, b::y)
end
Your second base case is also extraneous, so we could further revise this to
fun divide [] = ([], [])
| divide ((a, b)::xs) =
let
val (x, y) = divide xs
in
(a::x, b::y)
end

SML only accepting int list when it should be a real list

I am trying to write a simple add function that takes two real lists and adds the matching indices together and generates a real list, but for some reason I can't get it to accept real lists as the parameters, but instead only int lists.
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a :: b, x :: y) = (a + x) :: add (b,y)
When I try running my test input, val addTest = add([1.0, 2.0, 3.0], [0.1, 0.2, 0.3]); it gives me:
Error: operator and operand do not agree [tycon mismatch]
operator domain: int list * int list
operand: real list * real list
And I am just curious as to why SML is defaulting to an int list even though the "+" operand is used for both reals and ints. Shouldn't it be accepting `a list instead of just int lists?
Yes, + (along with other arithmetic operators) is overloaded but not parametrically polymorphic.
So you can do 1.0 + 1.0 and 1 + 1 and they give a real and an int respectively.
But fun f x y = x + y can infer to either, so the compiler defaults to the int overload.
As an addition to your own answer, you can do with a single : real in your code:
fun add ([], _) = []
| add (_, []) = []
| add (x::xs, y::ys) = (x + y : real) :: add (xs, ys)
and it will infer that you must mean real in all the other places, too.
You could generalise this operation into one called zipWith:
- fun zipWith f [] _ = []
| zipWith f _ [] = []
| zipWith f (x::xs) (y::ys) = f (x, y) :: zipWith f xs ys
> val ('a, 'b, 'c) zipWith = fn :
('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list
- val add = zipWith (op + : real * real -> real)
> val add = fn : real list -> real list -> real list
- add [1.0, 2.0, 3.0] [4.0, 5.0, 6.0];
> val it = [5.0, 7.0, 9.0] : real list
I found out that the default behavior for SML in a case like this is to default to int behavior, so if you have an operand that works for either reals or ints it will be evaluated as an int. As for the method above I was able to get my desired behavior by specifying the parameters in the tuple to be real lists like so:
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a::b : real list, x::y : real list) = (a + x) :: add (b,y)

right-hand-side of clause doesn't agree with function result type

Write a function remove_option, which takes a string and a string list. Return NONE if the string is not in the list, else return SOME xs where xs is identical to the argument list except the string is not in it. You may assume the string is in the list at most once. Use same_string, provided to you, to compare strings. Sample solution is around 8 lines.
The function type should be fn : string * string list -> string list option.Here is my code
fun same_string(s1 : string, s2 : string) =
s1 = s2
fun remove_option (str: string ,str_list : string list) =
case str_list of
[] => NONE
| x::xs => if same_string(x,str)
then SOME xs
else x :: remove_option( str,xs)
and the error report
hw2provided.sml:10.5-15.37 Error: right-hand-side of clause doesn't agree with f
unction result type [tycon mismatch]
expression: _ option
result type: string list
in declaration:
remove_option =
(fn (<pat> : string,<pat> : string list) =>
(case str_list
of <pat> => <exp>
| <pat> => <exp>))
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:292.17-292.20
So where is the bug ?
The problem is that you want to return a string list option but the line
else x :: remove_option( str,xs)
makes it seem that you want to return a string list
What you need to do with the return value of remove_option( str,xs) is
1) decide what to do if it is NONE
2) extract the string list strings (or whatever you want to call it) if it is of the form SOME strings, tack x onto the front of the list, and repackage it with SOME before returning it.
You seem comfortable with the use of case, so you could use it here.
Since John showed where the bug is, here are some extra comments:
Since the function same_string is not injected, it is superfluous. You might as well use =.
Recursive functions that return 'a option are kind of tricky, since you need to unpack the result:
fun remove_option (s1, []) = NONE
| remove_option (s1, s2::ss) =
if s1 = s2
then SOME ss
else case remove_option (s1, ss) of
NONE => NONE
| SOME ss' => SOME (s2::ss')
Generally, when you see the pattern
case x_opt of
NONE => NONE
| SOME x => SOME (f x))
this can be refactored into using e.g. Option.map : ('a -> 'b) -> 'a option -> 'b option:
Option.map f x_opt
In this case,
fun curry f x y = f (x, y)
fun remove_option (s1, []) = NONE
| remove_option (s1, s2::ss) =
if s1 = s2
then SOME ss
else Option.map (curry op:: s2) (remove_option (s1, ss))
where curry op:: s2, the function that puts s2 in front of a list.