-1

I have a function

(.#.) :: [a] -> Integer -> a                  -- 1-indexing with 'Integer'

xs .#. j = xs !! (fromIntegral $ j-1)

showIntegers :: [Integer] -> String

showIntegers r = let

      str = concat $ "List: " : [r (.#.) j | j <- [1..length r]]

How can I show r (.#.) j as a Char/String rather than an integer? I tried using show, but it gave me an error.

Here is an example of how I used show:

str = concat $ "List: " : [show $ r (.#.) j | j <- [1..length r]]

Example input and output:

> showIntegers [1,2,3]
List: 1 2 3  
jub0bs
  • 60,866
  • 25
  • 183
  • 186
Haani
  • 109
  • 3
  • 11
  • 1
    1. How did you use `show`and get an error? 2. Give an example of your wanted string for `showIntegers [1,2,3]` – Franky Feb 12 '15 at 17:50
  • 2
    What error? `*** Exception: Prelude.(!!): index too large` by any chance? Lists are zero-indexed, so you probably want `[0..length r - 1]`. – bergey Feb 12 '15 at 17:58
  • Oh I'm sorry I forgot to change the fact that I used 1 indexing rather than 0 indexing, I predefined a rule, I guess I should call it that, to change that. – Haani Feb 12 '15 at 18:01
  • `($)` has higher precedence than `(!!)`, so you should simply do `[show r !! j | j <- [1..length r]]` – Michal Seweryn Feb 12 '15 at 18:03
  • 1
    @MichalSeweryn: That would convert the list to a string and then take the index of the resultant string. Also use \` to denote a code segment. – Guvante Feb 12 '15 at 18:06
  • 2
    Using `r !! i` to access the elements of a list in Haskell is the last resort, since it is quite inefficient (lists are not arrays). Using a list comprehension over `[1 .. length r]` is a common antipattern. Don't write `[f (r !! i) | i <-[0..length r-1]]`, use instead `[f x | x<-r]` or `map f r`. – chi Feb 12 '15 at 18:10
  • As an aside, there's no reason to use Integer if you immediately convert them to Int anyway. – Rein Henrichs Feb 12 '15 at 19:06

2 Answers2

2

You should just use Data.List.intercalate or even better use unwords.

import Data.List
showIntegers :: [Integer] -> String
showIntegers r = "List: " ++ intercalate " " $ map show r
--showIntegers r = "List: " ++ unwords $ map show r

EDIT: In either case you should avoid using !! especially to enumerate the original list.

First I would get rid of .#. it is just going to confuse you to use a different numbering system, best to rip that bandaid off.

Next realize that [show $ r !! j <- 0 .. length r - 1] is the same as map show r (and the latter is standard).

Now going with that you have: concat $ "List: " : (map show r) which creates List: 123 because we lost the spaces.

We could reproduce the spaces but what is the difference between using intercalate and concat? Honestly the best solution without using intercalate would be to reproduce intercalate (whose source code is available on Hackage).

Community
  • 1
  • 1
Guvante
  • 18,775
  • 1
  • 33
  • 64
  • Would it be possible without predefined functions? I'm trying to understand how Haskell works and if I just use that it wouldn't help me understand how things work. – Haani Feb 12 '15 at 18:07
  • also, my professor insists that I use 1 indexing. I'm not sure why and I'm used to 0 indexing but I have to comply. – Haani Feb 12 '15 at 18:27
  • 1
    I think it's worth pointing out that `unwords` is the special case of `intercalate " "`, and `unwords` exists in `Prelude` already, you don't need to import `Data.List`. – bheklilr Feb 12 '15 at 18:53
0

Just remove the parenthesis around (.#.) and it works.

If you have an infix operator !#$ , with something before and after it, e.g. x !#$ y, you must not use parentheses. In the other cases, add parentheses, like in the type declaration.

(this technically answers the question, but Guvante's advice is better.)

Franky
  • 2,339
  • 2
  • 18
  • 27