How to return a tuple to a function in Haskell?

Asked

Viewed 298 times

1

I started messing with Haskell because of some college activity, and I’m having doubts about what the error in my code might be. The program will have two functions. 'tam', which will return the size of a string and statistics, who receives a String and returns a tuple of the type (String, Int):

  • The return string will be composed of the first and last letter of the input string separated by a dot, and:
  • The integer matches the size of the input string.

Input example:

statistics "carro"

-- Saída
("c.o", 5)

Or:

statistics "mala"

-- Saída:
("m.a", 4)

The code:

tam :: [a] -> Int
tam [] = 0
tam ( x:xs ) = 1 + tam xs

tupla :: (Integer, [Char])
statistics :: [Char] -> ([Char], Integer)

statistics string = print $ tupla
  type tupla :: ([Char], Integer)
  where tupla = ( let a = head string; b = '.'; c = last string in a+b+c,
                  tam string)

I got this mistake:

parse error on input `type'

I’ve tried it another way:

tam :: [a] -> Int
tam [] = 0
tam ( x:xs ) = 1 + tam xs

statistics :: [Char] -> ([Char], Integer)

statistics string = print $ tupla
  where tupla = (x, y)
  where x = (head string + "." + last string)
  where y = (tam string)

I’m getting this mistake:

parse error on input `where'
  • What is not working? Vale [Edit] your reply to add more details about the error. :)

1 answer

1

First, you don’t need to reinvent the wheel by creating a function tam, since, as in Haskell strings are lists of characters (Char), you can use the function length in a string, which will return its length.

Then the type annotation you are using for statistics:

statistics :: [Char] -> ([Char], Integer)

It is incorrect since statistics returns the value of the expression returned by the function print, which is a IO Monad "empty". Therefore, the annotation should be:

statistics :: [Char] -> IO ()

Or simply don’t create this annotation and let the compiler automatically infer the types for you (the Haskell compiler is excellent at this sort of thing).

There is also incorrect use of the clause where. No need to repeat, learn more here. The operator + is also being misused, since it should only be used with numbers, and in this case is being used to "concatenate" strings.

A solution is to simply return a string of characters (since head and last return, in a string, a Char):

statistics :: String -> IO ()
statistics str = print ([x, '.', y], len)
 where
  x   = head str
  y   = last str
  len = length str

Like [x, '.', y] is a list of three Chars, Haskell will interpret it as String, that is to say, [Char].

But the where nor is it necessary, since it is not avoiding any kind of repetition. I would personally only use it to make the code more readable or to avoid repetitions, which is not the case here.

Anyway, you can do it too:

statistics str = print ([head str, '.', last str], length str)

But remember that head and last will make an exception in case the past list is empty. It is worth taking care of it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.