Let recursiveness in Haskell - list

Could someone explain the behaviour of this little piece of code with the following input: [[1,2],[3,4]]?
infiniteList ls = let v = ls ++ v
in concat v
The result is an infinite list but I don't realise why. I've understood that the trick is in:
ls ++ v
But how exactly work the let since we do not define the initial value for the variable v?

To evaluate v, just replace it with its definition:
v = ls ++ v
= ls ++ ls ++ v
= ls ++ ls ++ ls ++ v
= ls ++ ls ++ ls ++ ls ++ v
= ls ++ ls ++ ls ++ ls ++ ls ++ v
= ls ++ ls ++ ls ++ ls ++ ls ++ ls ++ v
Clearly this will never end.

Related

Tail call optimization with a function returning a tuple

I have a simple function that splits a list at an index:
let rec split_at ls i =
match i with
| 0 -> ([], ls)
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
match split_at t (i - 1) with
| (left, right) -> ((h :: left), right)
Is there a way to get the OCaml compiler to optimize this function to use constant stack space?
I have tried using #tail_mod_cons but it doesn't work. I understand that the call is not really in tail position, but it feels like it should be optimizable.
Firstly, let's clean up your function by pattern matching on a tuple of i and ls and using a local let binding rather than that last match expression.
let rec split_at ls i =
match i, ls with
| 0, _ -> ([], ls)
| _, [] -> raise Not_found
| _, h::t ->
let (left, right) = split_at t (i - 1) in
(h::left, right)
As Jeffrey says, the cons (::) is not in tail call position, so tail_mod_cons does nothing for you. If we try to use it, we'll get a warning to that effect:
Lines 1-7, characters 33-20:
Warning 71 [unused-tmc-attribute]: This function is marked #tail_mod_cons
but is never applied in TMC position.
As also hinted, though, it's trivial to let your brain modify this for tail-recursion using an accumulator.
let split_at lst n =
let rec aux lst n first_part =
match n, lst with
| 0, _ -> (List.rev first_part, lst)
| _, [] -> raise Not_found
| _, h::t -> aux t (n - 1) (h::first_part)
in
aux lst n []
The function split_at can be written in a partial tail_mod_cons way if we split the construction of the new prefix from the part of the function returning the suffix using a reference:
let[#tail_mod_cons] rec split_at r ls i =
match i with
| 0 -> r := ls; []
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
h:: (split_at[#tailcall]) r t (i - 1)
let split_at ls i =
let r = ref [] in
let l = split_at r ls i in
l, !r
The way I understand it, "tail mod cons" works by passing an incomplete constructor into which the called function should place its answer. So to make the optimization work you have to be able to put your problem into a form for which this is a solution.
Maybe it would work if you split the problem into two parts. The first part duplicates the first n elements of the list. The second part returns all but the first n elements of the list.
The second part is trivial to implement tail recursively. And it seems like you should be able to duplicate a list using "tail mod cons".

Ocaml Pattern matching not doing as I expect

I'm having a little trouble with my OCaml program:
let moveRight ls i =
match getn ls (i+1) with
|O -> replacex (replacex ls i O) (i+1) R
|_ -> replacex (replacex ls i O) (i+2) R;
Replacex works, and replaces the i'th element in list ls with x.
But my program above doesn't.
It is supposed to do the following:
If a list is [R; L; O], and i = 1, it should change it to [O;L;R], but it doesn't. It seems to create the original list inside the new list and does this: [R; R; O; O; L; O].
Help would be appreciated, I'm not sure where I'm going wrong!
Thanks
EDIT:
replacex is as follows:
let replacex ls i x = firstx ls (i-1) # [x] # lastx ls ((length ls)-i);;
And it's dependant functions are:
let rec firstx ls i =
match ls with
| [] -> []
| x::xs -> if i <> 1 then x::firstx xs (i-1) else [x];;
let rec reverse ls =
match ls with
|[] -> []
| x::xs -> reverse xs # [x];;
let lastx ls i = reverse (firstx (reverse ls) i);;
let rec length ls =
match ls with
| [] -> 0
| x::xs -> 1+length xs;;
let rec getn ls i = match ls with
| [] -> raise (Failure "empty list")
| first::rest ->
if i = 0 then first
else getn rest (i-1);;
In fact, replacex function doesn't work correctly if you're trying to replace second element of the list. This leads to the call to firstx with second argument equal to 0. And your implementation of firstx returns a full list in that case. You should either fix indices in, or rethink what is first zero elements.

Haskell: Pattern Matching with Lists

I'm trying to make a function that takes in a list, and if one of the elements is negative, then any elements in that list that are equal to its positive counterpart should be changed to 0. Eg, if there is a -2 in a list, then all 2's in that list should be changed to 0.
Any ideas why it only works for some cases and not others? I'm not understanding why this is, I've looked it over several times.
changeToZero [] = []
changeToZero [x] = [x]
changeToZero (x:zs:y:ws) | (x < 0) && ((-1)*(x) == y) = x : zs : 0 : changeToZero ws
changeToZero (x:xs) = x : changeToZero xs
changeToZero [-1,1,-2,2,-3,3]
-- [-1,1,-2,2,-3,3]
changeToZero [-2,1,2,3]
-- [-2,1,0,3]
changeToZero [-2,1,2,3,2]
-- [-2,1,0,3,2]
changeToZero [1,-2,2,2,1]
-- [1,-2,2,0,1]
I think a list comprehension is both clearer and easier to get right here.
changeToZero xs = [if x > 0 && (-x) `elem` xs then 0 else x | x <- xs]
If you need something more efficient, you can build a set of the negative elements and check that instead of using elem.
import qualified Data.Set as Set
changeToZero' xs = [if (-x) `Set.member` unwanted then 0 else x | x <- xs]
where unwanted = Set.fromList $ filter (< 0) xs
you don't anctually remember which negative symbols you found in the list
import qualified Data.Set as S
changeToZero :: [Int] -> [Int]
changeToZero [] = []
changeToZero xs = reverse . snd $ foldl f (S.empty,[]) xs
where
f (negs,res) x | x < 0 = (S.insert (-x) negs, x:res)
| S.member x negs = (negs,0:res)
| otherwise = (negs,x:res)
Well, building on the answer from #jdevelop, if the negative has to appear before the positive in order to count, then you can build the result with a single pass over the input, without the need to reverse it:
import qualified Data.Set as S
import Control.Monad.State
changeToZero :: [Int] -> [Int]
changeToZero xs = evalState (mapM f xs) S.empty where
f x | x < 0 = modify (S.insert (-x)) >> return x
| otherwise = gets (S.member x) >>= \hasNeg -> return $ if hasNeg then 0 else x
In this way, you can get an answer to
take 4 $ changeToZero $ 1 : (-2) : 3 : 2 : undefined
where the other solutions will fail.
** Edit **
Here is the same thing, but without the State monad, which makes it easier to understand:
changeToZero' :: [Int] -> [Int]
changeToZero' = go S.empty where
go _ [] = []
go s (x:xs) | x < 0 = x : go (S.insert (-x) s) xs
| S.member x s = 0 : go s xs
| otherwise = x : go s xs

how to modify the i-th element of a Haskell List?

I'm looking for a way to modify the i-th element of haskell List. let says foobar is such a function, then the following works.
let xs = ["a","b","c","d"]
foobar xs 2 "baba" -- xs = ["a","b","baba","d"]
thanks for any reply!
You can do it with splitAt:
Prelude> let xs = ["a","b","c","d"]
Prelude> (\(l,_:r)->l++"baba":r) $ splitAt 2 xs
["a","b","baba","d"]
let xs = ["a","b","c","d"]
take 2 xs ++ ["baba"] ++ drop 3 xs
change n x = zipWith (\k e -> if k == n then x else e) [0..]
A simple function to do it directly:
replaceAt _ _ [] = []
replaceAt 0 x (_:ys) = x:ys
replaceAt n x (y:ys) = y:replaceAt (n - 1) x ys

Haskell Creating list of numbers

Hi
Im new to Haskell and wish to write a simple code.
I want to write a function which creates a list of numbers.
Where it starts of with 1 and increase with 2n+1 and 3n+1
so for example output should be like
take 6 myList = [1,3,4,7,9,10]
I think i need to use recursion but not sure how to do
it in list format.
Any help will be appreciated. Thanks
Actually, I am not sure if I get your idea.
But Is this what you want?
generator list = list ++ generator next
where
next = (map (\n -> 2 * n + 1) list) ++ (map (\n -> 3 * n + 1) list)
Oh, you can use generator [1] to fire up. like this:
take 100 $ generator [1]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) | x == y = x : merge xs ys
| x < y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
print $ take 10 $ merge [1,3..] [1,4..]
--[1,3,4,5,7,9,10,11,13,15]
As luqui said, we could use info such as do duplicates matter and does order matter. If the answers are no and no then a simple concatMap works fine:
myList = 1 : concatMap (\n -> 2*n+1 : 3*n+1 : []) myList
Results in:
> take 20 myList
[1,3,4,7,10,9,13,15,22,21,31,19,28,27,40,31,46,45,67,43]
If the answers are yes and yes then I imagine it could be cleaner, but this is sufficient:
myList = abs
where
abs = merge as bs
as = 1 : map (\n -> 2*n+1) abs
bs = 1 : map (\n -> 3*n+1) abs
merge (x:xs) (y:ys)
| x == y = x : merge xs ys
| x < y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
Results in:
> take 20 myList
[1,3,4,7,9,10,13,15,19,21,22,27,28,31,39,40,43,45,46,55]