Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read list of numbers in haskell

Tags:

haskell

I'm learning Haskell and I was working in a problem where I had to remove repeated consecutive numbers from a list, so I wrote this program.

destutter::[Integer] -> [Integer]
destutter [] = []
destutter (fst:snd:t) | fst == snd = destutter (snd : t)
destutter (h:t) = [h] ++ (destutter t)

It works fine for the input test that I had which was a list

input = [200, 271, 305, 305, 180]

now I have a text file with a lot of inputs and I need to use my function on it, if it was in C++ I would do something like:

while(cin>> x)
    v.push_back(x);
destutter(x);

But I'm completely new to Haskell and I have no idea how I would do that on this language. I found this answer on stack overflow but was not able to modify the code for my use, so if someone could give a noob a hand I would be very thankful. My text file has the following structure:

260
221
235
268
...
like image 210
João Areias Avatar asked Sep 27 '18 02:09

João Areias


People also ask

What does Elem do in Haskell?

Elem Function This function is used to check whether the supplied list contains a specific element or not. Accordingly, it either returns a true or a false. The following code checks whether the supplied list of elements contains the value 786.


1 Answers

Use getContents to get all input from stdin. It does so lazily, so don't worry about running out of memory.

Then separate it into lines with lines (or write your own function to divide it into lines for practice). This makes a [String] with each list element being a line in the input.

Then map read over each element (or write your own map and read functions for practice) to turn each element from a String into an Integer.

Now you have an [Integer] that you can destutter.

destutter::[Integer] -> [Integer]
destutter [] = []
destutter (fst:snd:t) | fst == snd = destutter (snd : t)
destutter (h:t) = [h] ++ (destutter t)

main :: IO ()
main = do
  userInput <- getContents
  let numbers = map read (lines userInput) :: [Integer]
  print $ destutter numbers

A few notes on improving destutter a little and a lot

You shouldn't use this if you're writing an assignment for school (your destutter definitely works), but as far as destutter goes, there are a few things to help your learning.

A minor stylistic issue is that x and xs (or y and ys or anything of that pattern) are used for head and tail rather than h and t.

[x] ++ xs is harder to read (and more expensive) than x:xs, so your third pattern for destutter can be done like this:

destutter (x:xs) = x:destutter xs

(:) is useful for detaching elements from the front of a list in patterns and for attaching elements to the front of a list outside of patterns.


Don't worry about this so much now, but later on, after you get the hang of writing functions from scratch, you'll begin to use prewritten functions like Data.List.group, which is quite similar to destutter as it groups equal neighbors in a list into their own sublist. If you take the first element (head) of each sublist (they're all equal, so one's as good as another), it does destutter:

import Data.List (group)

destutter :: Eq a => [a] -> [a]
destutter xs = map head (group xs)

So, basically, it turns [1, 2, 2, 3] into [[1], [2, 2], [3]], then it takes the first element of each sublist to get [1, 2, 3].

One thing to take from that is that you already know how to write a function (destutter) quite similar to those that they include with Haskell.

like image 190
Chai T. Rex Avatar answered Oct 11 '22 09:10

Chai T. Rex