Why is my implementation of "map" processing elements in reverse order? - ocaml

This is my implementation of map:
let rec map f lst =
match lst with
| [] -> []
| hd :: tl -> f hd :: map f tl
I tried to run it like this:
(* Print the given int, then return the given int. *)
let print_id n =
print_int n;
print_newline ();
n
let () = ignore (map print_id [1; 2; 3])
Although map print_id [1; 2; 3] returns [1; 2; 3], the code above prints:
3
2
1
It seems that the list is being processed in reverse order! What is happening?

OCaml doesn't guarantee an order for evaluation of an expression. So this expression:
f hd :: map f tl
is permitted to evaluate the call to map before the call to f.
You can use let to guarantee an evaluation order:
let x = f hd in
x :: map f tl

With following reduction order for the function map, things will be clear enough to you hopefully.
map print_id [1; 2; 3]
print_id 1 :: map print_id [2; 3]
print_id 1 :: print_id 2 :: map print_id [3]
print_id 1 :: print_id 2 :: print_id 3 :: map print_id []
print_id 1 :: print_id 2 :: print_id 3 :: [] (* print_id 3, prints 3 and returns 3 *)
print_id 1 :: print_id 2 :: 3 :: [] (* print_id 2, prints 2 and returns 2 *)
print_id 1 :: 2 :: 3 :: [] (* print_id 1, prints 1 and returns 1 *)
1 :: 2 :: 3 :: [] (* List Construction yields [1; 2; 3] *)

One more point, in addition to the excellent answers already offered. The standard library implements both List.map and List.iter. The latter has the type ('a -> unit) -> 'a list -> unit and is typically used when side effects are the point of iterating over a list, rather than constructing a new list.
You can trivially implement this yourself. It has the benefit of making evaluation order explicitly what you want, and it's naturally tail-recursive.
let rec iter f = function
| [] -> ()
| hd::tl -> f hd; iter f tl

Related

Reversing a list in SML

fun reverse ( [] ) = ( [] )
| reverse (x::xs) = reverse (xs) :: [x]
why my this function of reversing a list is not working
Your function has type 'a list -> 'a list. :: has type 'a -> 'a list -> 'a list. Thus you can't pass the result of calling reverse as the first argument to ::.
You could use # as suggested by JRose because that has type 'a list -> 'a list -> 'a list and will concatenate the two lists but that is inefficient compared to ::. # is O(n). Using it makes reverse have O(n^2) runtime efficiency.
Instead, let's use a tail-recursive helper function to build up an accumulator list in reverse order using ::, then return that. Because :: is O(1), this has O(n) runtime efficiency which is much better.
fun reverse lst =
let
fun aux [] acc = acc
| aux (x::xs) acc = aux xs (x :: acc)
in
aux lst []
end
Consider reversing [1, 2, 3]:
reverse [1, 2, 3]
aux [1, 2, 3] []
aux [2, 3] [1]
aux [3] [2, 1]
aux [] [3, 2, 1]
[3, 2, 1]
Further reading on the efficiency of # and ::. The link talks about OCaml, but the core principles are the same in SML.

Haskell sum a list with testcase

So I have the following code:
data List = Empty | Cons Integer List deriving Show
list = Cons 1 (Cons 7 (Cons 9 (Cons 3 Empty)))
Now I want to sum up the list created from above with this function:
-- sumList
sumList :: List -> Integer
sumList = sum
I do also have a testcase:
testSum = putStrLn ("expected: 20\ncomputed: " ++ show (sumList list))
My problem is, that I get the following error message:
• Couldn't match type ‘List’ with ‘t0 Integer’
Expected type: List -> Integer
Actual type: t0 Integer -> Integer
• In the expression: sum
In an equation for ‘sumList’: sumList = sum
data List = Empty | Cons Integer List deriving Show
sumList :: List -> Integer
sumList Empty = 0
sumList (Cons x xs) = x + sumList xs
As you can see, since List is a recursive data type, meaning it can hold instances of itself, we need to recursively open the members and add them all together.
As a test:
λ> list = Cons 1 (Cons 7 (Cons 9 (Cons 3 Empty)))
λ> sumList list
20
In your code, you are using sum from Data.Foldable. sum has the following signature:
λ> :t sum
sum :: (Foldable t, Num a) => t a -> a
This means that it needs a data type with an instance of the Foldable class to be able to work on, which List obviously does not have.

Couldn't match expected type `[a]' with actual type `a'

I have the following function which should adds up all numbers in a given list up to the current position. For example, subtotal [1, 2, 3, 4] = [1, 3, 6, 10], because 1 = 1, 1 + 2 = 3, 1 + 2 + 3 = 6 and 1 + 2 + 3 + 4 = 10.
Here's my code:
subtotal :: Num a => [a] -> [a]
subtotal [] = []
subtotal xs = [y | n <- [1..length xs], y <- sum(take n xs)]
The problem is Im getting this error:
cw.hs:3:46: error:
* Couldn't match expected type `[a]' with actual type `a'
`a' is a rigid type variable bound by
the type signature for:
subtotal :: forall a. Num a => [a] -> [a]
at cw.hs:1:1-31
* In the expression: sum (take n xs)
In a stmt of a list comprehension: y <- sum (take n xs)
In the expression:
[y | n <- [1 .. length xs], y <- sum (take n xs)]
* Relevant bindings include
xs :: [a] (bound at cw.hs:3:10)
subtotal :: [a] -> [a] (bound at cw.hs:2:1)
|
3 | subtotal xs = [y | n <- [1..length xs], y <- sum(take n xs)]
| ^^
How can I fix it?
sum(take n xs) is not a list, so you can not iterate over it. In order to add the result of an expression to a list you put the expression in the head of the list comprehension:
subtotal :: Num a => [a] -> [a]
subtotal xs = [sum (take n xs) | n <- [1..length xs]]
But you here use length. length is a bit a dangerous function since lists can be infinite, and then your function will simply keep looping, and never return an element. You can use inits however to obtain all the lists:
Prelude Data.List> inits [1,4,2,5]
[[],[1],[1,4],[1,4,2],[1,4,2,5]]
So you can use:
import Data.List(inits)
subtotal :: Num a => [a] -> [a]
subtotal xs = [sum sub | sub <- tail (inits xs)]
But this is still not very effectively: now we calculate the sum of every sublist. But a problem here is that we calculate the sum of every list separately. This is weird since the sum of the i-th result is simply the sum of the i-1-th result plus the i-th element of xs. We can use scanl1 :: (a -> a -> a) -> [a] -> [a]:
subtotal :: Num a => [a] -> [a]
subtotal xs = scanl1 (+) xs
or even more simple and elegant:
subtotal :: Num a => [a] -> [a]
subtotal = scanl1 (+)
In a list comprehension, the statement y <- ys means that ys is a list and y iterates over the elements of that list. So y <- sum (take n xs) means that sum produces a list and you iterate over that list. But sum only produces a single number, not a list; so you get an error.
You want to use let instead of <- to assign simple expressions:
subtotal xs = [y | n <- [1..length xs], let y = sum(take n xs)]
Or just put the expression directly into the head of the comprehension:
subtotal xs = [sum (take n xs) | n <- [1..length xs]]
PS: Your first case (for the empty list) is redundant. It's just a special case of the second.

Nested chunksOf in Haskell?

Say I want to do this:
nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4] == [[[1,1,1], [2,2,2]], [[3,3,3], [4,4,4]]]
In Python, I can do this
def group(a, *ns):
for n in ns:
a = [a[i:i+n] for i in xrange(0, len(a), n)]
return a
group([1,1,1,2,2,2,3,3,3,4,4,4], 3, 2) == [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
But in Haskell, I can't just say
nestedChunksOf :: [Int] -> [a] -> [[a]]
or
nestedChunksOf :: [Int] -> [a] -> [[[a]]]
So how can I achieve the same thing in Haskell?
A function like nestedChunksOf can't be done directly in Haskell, at least not one which operates on normal lists. The depth of the list is part of the type, so you can't have an arbitrary depth specified by a parameter.
But what you can do is nest chunksOf.
If we define chunksOf like this:
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs = fxs : chunksOf n sxs
where (fxs, sxs) = splitAt n xs
We can then nest it:
Main> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[1,1,1],[2,2,2],[3,3,3],[4,4,4]]
*Main> chunksOf 2 $ chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
I hope that accomplishes what you wanted!
As stated in the other answers, this can't be done directly as in Haskell you always need to know the type of an expression and thus distinguish between [a], [[a]] etc. However, using polymorphic recursion you can define a data type that allows such arbitrary nesting by wrapping each level in a constructor:
data NestedList a = Value a | Nested (NestedList [a])
deriving (Show)
So just Value is isomorphic to a, Nested (Value ...) is isomorphic to [a], double Nested to [[a]] etc. Then you can implement
chunksOf :: Int -> [a] -> [[a]]
...
nestedChunksOf :: [Int] -> [a] -> NestedList a
nestedChunksOf [] xs = Nested (Value xs)
nestedChunksOf (c:cs) xs = Nested (nestedChunksOf cs $ chunksOf c xs)
And indeed
print $ nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4]
outputs
Nested (Nested (Nested (Value [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]])))
It can be done fairly easily with dependent types.
We'd like to express that the length of the [Int] argument determines the type of the result. We need two things for that: a list type with fixed length, and a type-level function which computes the return type from the length:
{-# LANGUAGE DataKinds, GADTs, TypeFamilies #-}
import Data.List.Split
data Nat = Z | S Nat -- natural numbers (zero, successor)
data Vec n a where -- "n" length lists of "a" elements
Nil :: Vec Z a
(:>) :: a -> Vec n a -> Vec (S n) a
infixr 5 :>
type family Iterate n f a where
Iterate Z f a = a
Iterate (S n) f a = f (Iterate n f a)
Iterate n f a applies the type constructor f n times to an argument. For example, Iterate (S (S Z)) [] Int reduces to [[Int]]. nestedChunksOf can be written directly now:
nestedChunksOf :: Vec n Int -> [a] -> Iterate (S n) [] a
nestedChunksOf Nil as = as
nestedChunksOf (n :> ns) as = chunksOf n $ nestedChunksOf ns as
Usage:
> nestedChunksOf (2 :> 3 :> Nil) [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
This can not be achieved in Haskell through "normal" means because it would require a dependent type - the type of the result depends on the length of the first argument.
Perhaps a tuple solution would be acceptable?
{-# Language TypeFamilies #-}
{-# Language FlexibleInstances #-}
import Data.List.Split
class NestedChunksOf a where
nco :: a -> [b] -> AList a b
type AList a b :: *
instance NestedChunksOf (Int,Int) where
nco (f,s) xs = chunksOf f (chunksOf s xs)
type AList (Int,Int) a = [[[a]]]
-- More instances as desired.

haskell, is number in one list is within the range of a second list?

What is the best way to find out if a number in a list is within the range of a second list, using a Maybe data type?
What I have so far:
getElems :: [Int] -> [a] -> [Maybe a]
getElems [xs] ys
| head(tail[(xs)]) > head(tail[(ys)]) = [Nothing]
| otherwise = [Just xs]
It needs to return those elements that correspond to the positions specified. Depending on if a position is greater than the list size it returns Nothing, else Just value.
For example:
getElems [2,4] [1..10] ) [Just 3,Just 5]
getElems [2,4] [1..4] ) [Just 3,Nothing]
You can write an getElementByIndex which does that for a single list:
getElementByIndex :: Int -> [a] -> Maybe a
getElementByIndex n [] = Nothing
getElementByIndex n (x:xs) = if (n == 0)
then Just x
else getElementByIndex (n - 1) xs
And then just map it to get an answer:
getElems :: [Int] -> [a] -> [Maybe a]
getElems xs ys = map (\x -> getElementByIndex x ys) xs
Demo in ghci:
λ> getElems [2,4] [1..10]
[Just 3,Just 5]
λ> getElems [2,4] [1..4]
[Just 3,Nothing]