-1

I'm using a data type to emulate the Heterogeneous List:

data Nested a = Elem a | List [Nested a]
            deriving (Show)

So that I can express data like List [Elem 1, Elem 2, List [Elem 3, Elem 4], List [Elem 5], Elem 6].

Here I'm writing a function to act like the normal append function to concatenate my heterogeneous lists:

appendn                 :: Nested a -> Nested a -> Either String (Nested a)
appendn (Elem a) (List x)       = Left "error: wrong argument"
appendn (List x) (Elem a)       = Left "error: wrong argument"
appendn (List []) (List x)      = Right (List x)
appendn (List (x:xs)) (List y)  = Right (List (x:appendn (List xs) (List y))

But I'm always getting a parse error at the last row. I'm wondering whether I can use : operator here to append List. Could someone help? Thanks.

J Freebird
  • 3,664
  • 7
  • 46
  • 81
  • 1
    This problem seems to be giving a lot of people problems: http://stackoverflow.com/questions/21176557/haskell-either-string-nestedlist-a-why-doesnt-it-work/ – user2407038 Jan 19 '14 at 08:02

3 Answers3

1

Count the left and right parenthesis. Do they match?

md2perpe
  • 3,372
  • 2
  • 18
  • 22
1

A couple of points:

  1. You have a missing case: if both arguments are in Elem

  2. Your function results in an Either String (Nested a), however in the last case definition is:

    ... appendn (List (x:xs)) (List y) = Right (List (x:appendn (List xs) (List y))

Here we are attempting to cons (:) a value x :: Nested a onto a non-list appendn (List xs) (List y) :: Either String (Nested a)

Potential Solution

appendn :: Nested a -> Nested a -> Either String (Nested a)

--  if an `Elem` is given as either argument, the result is
--  a `Left` error.
appendn (Elem a) _           = Left "error: wrong argument"
appendn _ (Elem a)           = Left "error: wrong argument"

--  Otherwise, we must have two `List`; the result of which
--  can just be `Right` of a new `List`, with the inner list
--  being the two lists appended together.
appendn (List xs) (List ys)  = Right (List (xs ++ ys))

A few test cases follow:

$ appendn (Elem 2) (Elem 3)
= Left "error: wrong argument"

$ appendn (List [Elem 1]) (Elem 2)
= Left "error: wrong argument"

$ appendn (Elem 2) (List [Elem 1])
= Left "error: wrong argument"

$ appendn (List [Elem 1, Elem 2]) (List [])
= Right (List [Elem 1,Elem 2])

$ appendn (List [Elem 1, Elem 2]) (List [Elem 3, Elem 4])
= Right (List [Elem 1,Elem 2,Elem 3,Elem 4])

Is there a reason Either is used here, as opposed to Maybe?

Hope this helps!

LiamGoodacre
  • 502
  • 3
  • 9
  • Thanks Liam, this really helps. I'm just more familiar with Either here, I don't know much about Maybe. Probably it's a better choice. Thanks. – J Freebird Jan 19 '14 at 19:16
0

Apart from parentesis mismatch, you also have a type error. You can't use (:) function with "List" argument, you'll have to unpack it.

BTW, why don't you just use the (++) function?

MigMit
  • 1,698
  • 12
  • 14