I m a newbie to Haskell. I am pretty good with Imperative languages but not with functional. Haskell is my first as a functional language.
I am trying to figure out, how to get the index of the smallest element in the list where the minimum element is defined by me.
Let me explain by examples.
For example :
Function signature
minList :: x -> [x]
let x = 2
let list = [2,3,5,4,6,5,2,1,7,9,2]
minList x list --output 1 <- is index
This should return 1. Because the at list[1] is 3. It returns 1 because 3 is the smallest element after x (=2).
let x = 1
let list = [3,5,4,6,5,2,1,7,9,2]
minList x list -- output 9 <- is index
It should return 9 because at list[9] is 2 and 2 is the smallest element after 1. x = 1 which is defined by me.
What I have tried so far.
minListIndex :: (Ord a, Num a) => a -> [a] -> a
minListIndex x [] = 0
minListIndex x (y:ys)
| x > y = length ys
| otherwise = m
where m = minListIndex x ys
When I load the file I get this error
• Couldn't match expected type ‘a’ with actual type ‘Int’
‘a’ is a rigid type variable bound by
the type signature for:
minListIndex :: forall a. (Ord a, Num a) => a -> [a] -> a
at myFile.hs:36:17
• In the expression: 1 + length ys
In an equation for ‘minListIndex’:
minListIndex x (y : ys)
| x > y = 1 + length ys
| otherwise = 1 + m
where
m = minListIndex x ys
• Relevant bindings include
m :: a (bound at myFile.hs:41:19)
ys :: [a] (bound at myFile.hs:38:19)
y :: a (bound at myFile.hs:38:17)
x :: a (bound at myFile.hs:38:14)
minListIndex :: a -> [a] -> a (bound at myFile.hs:37:1)
When I modify the function like this
minListIndex :: (Ord a, Num a) => a -> [a] -> a
minListIndex x [] = 0
minListIndex x (y:ys)
| x > y = 2 -- <- modified...
| otherwise = 3 -- <- modifiedd
where m = minListIndex x ys
I load the file again then it compiles and runs but ofc the output is not desired.
What is the problem with
| x > y = length ys
| otherwise = m
?
In short: Basically, I want to find the index of the smallest element but higher than the x which is defined by me in parameter/function signature.
Thanks for the help in advance!
minListIndex :: (Ord a, Num a) => a -> [a] -> a
The problem is that you are trying to return result of generic type a but it is actually index in a list.
Suppose you are trying to evaluate your function for a list of doubles. In this case compiler should instantiate function's type to Double -> [Double] -> Double which is nonsense.
Actually compiler notices that you are returning something that is derived from list's length and warns you that it is not possible to match generic type a with concrete Int.
length ys returns Int, so you can try this instead:
minListIndex :: Ord a => a -> [a] -> Int
Regarding your original problem, seems that you can't solve it with plain recursion. Consider defining helper recursive function with accumulator. In your case it can be a pair (min_value_so_far, its_index).
First off, I'd separate the index type from the list element type altogether. There's no apparent reason for them to be the same. I will use the BangPatterns extension to avoid a space leak without too much notation; enable that by adding {-# language BangPatterns #-} to the very top of the file. I will also import Data.Word to get access to the Word64 type.
There are two stages: first, find the index of the given element (if it's present) and the rest of the list beyond that point. Then, find the index of the minimum of the tail.
-- Find the 0-based index of the first occurrence
-- of the given element in the list, and
-- the rest of the list after that element.
findGiven :: Eq a => a -> [a] -> Maybe (Word64, [a])
findGiven given = go 0 where
go !_k [] = Nothing --not found
go !k (x:xs)
| given == xs = Just (k, xs)
| otherwise = go (k+1) xs
-- Find the minimum (and its index) of the elements of the
-- list greater than the given one.
findMinWithIndexOver :: Ord a => a -> [a] -> Maybe (Word64, a)
findMinWithIndexOver given = go 0 Nothing where
go !_k acc [] = acc
go !k acc (x : xs)
| x <= given = go (k + 1) acc xs
| otherwise
= case acc of
Nothing -> go (k + 1) (Just (k, x)) xs
Just (ix_min, curr_min)
| x < ix_min = go (k + 1) (Just (k, x)) xs
| otherwise = go (k + 1) acc xs
You can now put these functions together to construct the one you seek. If you want a general Num result rather than a Word64 one, you can use fromIntegral at the very end. Why use Word64? Unlike Int or Word, it's (practically) guaranteed not to overflow in any reasonable amount of time. It's likely substantially faster than using something like Integer or Natural directly.
It is not clear for me what do you want exactly. Based on examples I guess it is: find the index of the smallest element higher than x which appears after x. In that case, This solution is plain Prelude. No imports
minList :: Ord a => a -> [a] -> Int
minList x l = snd . minimum . filter (\a -> x < fst a) . dropWhile (\a -> x /= fst a) $ zip l [0..]
The logic is:
create the list of pairs, [(elem, index)] using zip l [0..]
drop elements until you find the input x using dropWhile (\a -> x /= fst a)
discards elements less than x using filter (\a -> x < fst a)
find the minimum of the resulting list. Tuples are ordered using lexicographic order so it fits your problem
take the index using snd
Your function can be constructed out of ready-made parts as
import Data.Maybe (listToMaybe)
import Data.List (sortBy)
import Data.Ord (comparing)
foo :: (Ord a, Enum b) => a -> [a] -> Maybe b
foo x = fmap fst . listToMaybe . take 1
. dropWhile ((<= x) . snd)
. sortBy (comparing snd)
. dropWhile ((/= x) . snd)
. zip [toEnum 0..]
This Maybe finds the index of the next smallest element in the list above the given element, situated after the given element, in the input list. As you've requested.
You can use any Enum type of your choosing as the index.
Now you can implement this higher-level executable specs as direct recursion, using an efficient Map data structure to hold your sorted elements above x seen so far to find the next smallest, etc.
Correctness first, efficiency later!
Efficiency update: dropping after the sort drops them sorted, so there's a wasted effort there; indeed it should be replaced with the filtering (as seen in the answer by Luis Morillo) before the sort. And if our element type is in Integral (so it is a properly discrete type, unlike just an Enum, thanks to #dfeuer for pointing this out!), there's one more opportunity for an opportunistic optimization: if we hit on a succ minimal element by pure chance, there's no further chance of improvement, and so we should bail out at that point right there:
bar :: (Integral a, Enum b) => a -> [a] -> Maybe b
bar x = fmap fst . either Just (listToMaybe . take 1
. sortBy (comparing snd))
. findOrFilter ((== succ x).snd) ((> x).snd)
. dropWhile ((/= x) . snd)
. zip [toEnum 0..]
findOrFilter :: (a -> Bool) -> (a -> Bool) -> [a] -> Either a [a]
findOrFilter t p = go
where go [] = Right []
go (x:xs) | t x = Left x
| otherwise = fmap ([x | p x] ++) $ go xs
Testing:
> foo 5 [2,3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 4
> foo 2 [2,3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 1
> foo 1 [3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 9
I want to print a list with different element in it (for educational purpose)
I have read a tutorial that explain how to store different type in list.
type _ list =
[] : unit list
| ( :: ) : 'b * 'a list -> ('b ->'a) list;;
1 :: "e" :: 'r' :: [];; (* this is allowed *)
how I can do something like this pseudo-code:
match typeof(my_expr) with
int -> print_int
| string -> print_string
we will have "1,e,r" printed.
Some solutions i have searched
Change my type in text and printing it
Use a different type definition maybe ('a, 'b) list ?
I ask this because the OCaml toplevel know the type of every variable and show always the type in the right format: can I call this printer ?
Is there a solution only for toplevel that we can install with the #install_printer ?
I know that compiler discard type's info after the type checking pass.
The printer of the toplevel should work fine:
[1; "one"; 1.];;
- : (int -> string -> float -> unit) list =
(::) (1, (::) ("one", (::) (1., [])))
(The unoptimal printing is an unfortunate consequence of ensuring that values printed by the toplevel can be copy-pasted back to the top-level and yields the same value)
But this is only possible outside of the language itself: the toplevel printers can inspect the typing environment which is purposefully not possible in the language itself. Indeed functions like typeof would break parametricity. There is thus no universal printer function in OCaml (without looking at the internal memory representation) and no universal heterogeneous list printer.
If you want to print an heterogeneous list, there are three possible paths:
print a specific type of the heterogeneous list
let print_concrete ppf (x::y::z::rest) = Format.fprintf ppf "%f %f %f" x y z
(Contrary to appearance, this function is total: its type makes it impossible to use on lists with fewer than three elements)
Use heterogeneous lists that always pack a printing function along its main value
type 'a printer = Format.formatter -> 'a -> unit
type _ showable_list =
| [] : unit showable_list
| (::):
('a * 'a printer) * 'b showable_list
-> ('a -> 'b) showable_list
let rec print: type a. a showable_list printer =
fun ppf l -> match l with
| [] -> ()
| (a,printer) :: rest -> Format.fprintf ppf "%a# %a" printer a print rest
provide a matching heterogeneous list of printing functions
type 'a plist =
| []: unit plist
| (::): 'a printer * 'b plist -> ('a -> 'b) plist
let rec print: type l. l plist -> l list printer = fun printers ppf values ->
match printers, values with
| [], [] -> ()
| p :: prest, a :: rest -> Format.fprintf ppf "%a# %a" p a (print prest) rest
The fact that you often need to specialize the heterogeneous list type may make it worthwhile to introduce a functor for generating them:
module Hlist(Specialization: sig type 'a t end) = struct
open Specialization
type 'a list =
| []: unit list
| (::): 'a t * 'b list -> ('a -> 'b) list
end
then the previous specialized type can be constructed with
module Showable_list = Hlist(struct type 'a t = 'a * 'a printer end)
module Printer_list = Hlist (struct type 'a t = 'a printer end)
So I have this exercise:
filter (fun x -> x = 0) [(1,0);(2,1);(3,0);(4,1)];;
result int list [1;3]
So basically you have to match your x in fun with the second number in list and if its the same you create new list with the first number.
My solution but is wrong
let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [];;
I get the following error when i want to try the code:
Error: This expression has type int but an expression was expected of
type
int -> bool
I can't reproduce the problem you report. Here's what I see when I try your code:
$ ocaml
OCaml version 4.02.1
# let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [] ;;
val filter : 'a -> ('b * 'a) list -> 'b list = <fun>
# filter 0 [(1,0); (2,1); (3,0)];;
- : int list = [1]
There are no errors, but it gets the wrong answer. That's what I would expect looking at your code.
The error that you are getting is saying that somewhere the compiler is expecting an int -> bool function, but you are giving it an int. The reason you get this error is because you have an equality (f = snd x), where f is of type int -> bool and snd x is of type int. both arguments given to the equality must be of the same type. Instead, what you want to do is simply branch on the result of applying f to the second element of x, such as:
let rec filter f = function
| []->[]
| x::l -> if f (snd x) then fst x :: filter f l else [];;
That said, I would recommend using pattern matching instead of fst and snd, such as:
let rec filter f l =
match l with
| [] -> []
| (x,y)::l -> if f y then x :: filter f l else filter f l
Note that f y will return something of type bool, which will then determine which branch to take.
Altough Matts answer is right. It's good to just reuse existing functions instead of writing a special from the ground up:
[(1,0);(2,1);(3,0);(4,1)]
|> List.filter (fun (_, x) -> x = 0)
|> List.map fst
I have a assignment which requires writing a code to union list without using any library functions
this is my code
let rec union (l1:'a list) (l2:'a list) =
let rec f x l = match l with
| [] -> true
| hd::tl ->
if x = hd then false else f x tl
in
match l2 with
| [] -> l1
| hd::tl ->
if f hd l1 then
union hd::l1 tl
else
union l1 tl
but the compiler said that "This expression has type 'a but an expression was expected of type 'a list The type variable 'a occurs inside 'a list"
can somebody helps me to find out where did I do wrong? thanks
I think you just need some parentheses on the last line:
if f hd l1 then union (hd::l1) tl else union l1 tl
In OCaml function application (as in f x) has very high precedence. So without these parens the expression is interpreted as (union hd) :: (l1 tl).
(This code is pretty nice. Maybe rename f to something more descriptive such as notmem.)
This is just an exercise (I realize that the functions mentioned below are already implemented in List).
Suppose that I have an interface that includes the following lines
val length : 'a list -> int
val fold : init:'acc -> f:('acc -> 'a -> 'acc) -> 'a list -> 'acc
...and that I implement fold like this:
let rec fold ~init ~f l =
match l with
| [] -> init
| h :: t -> fold ~init:(f init h) ~f:f t
I expected to now be able to implement length like this
let length = fold ~init:0 ~f:(fun c _ -> (c + 1))
...but the compiler complains with
Values do not match:
val length : '_a list -> int
is not included in
val length : 'a list -> int
Of course, I know that I can implement length like this
let length l = fold ~init:0 ~f:(fun c _ -> (c + 1)) l
...but I don't understand why I can't remove the trailing l from both sides of the =.
Where am I going wrong?
This is the value restriction. Your definition of length is not a value in a very technical sense. There are some good discussions of the issue already here on Stack Overflow. I'll look for a good one.
Here is a pretty good one:
Why does a partial application have value restriction?