Reputation:
I am trying to append function that works on Nested Lists like regular lists. I want to use Either String (Nested a) so that it returns error or the appended list. But it keeps failing. I am not doing NestedList[NestedList a] anywhere. Why does it say it expected [NestedList (NestedList a)]
module Main where
data NestedList a=Elem a | List[NestedList a] deriving Show
flatten ::NestedList a->[a]
flatten (Elem x)=[x]
flatten (List(x:xs))=flatten(x)++flatten(List xs)
--flatten NestedList (x:xs)=flatten(x)++flatten(xs)
flatten(List [])=[]
------------------
count::[a]->Int
count a=length (a)
-----------------
append::NestedList a->NestedList a->Either String (NestedList a)
append (_) (Elem a)=Left "Elements are not allowed"
append (Elem a) (_)=Left "Elements are not allowed"
append (List a) (List b)=Right (List (flatten(List a)++flatten(List b)))
-------------------
main=do
print(flatten (List[Elem 1, Elem 2,List[Elem 1, Elem 2 ]]))
print(count(flatten (List[Elem 1, Elem 2,List[Elem 1, Elem 2 ]])))
print(append (List[List[Elem 1, Elem 2 ]]) (List[Elem 1, Elem 2,List[Elem 1, Elem 2 ]] ))
gives me this error
flatten_list.hs:18:52:
Couldn't match type `a' with `NestedList a'
`a' is a rigid type variable bound by
the type signature for
append :: NestedList a
-> NestedList a -> Either String (NestedList a)
at flatten_list.hs:15:9
Expected type: [NestedList (NestedList a)]
Actual type: [NestedList a]
In the first argument of `List', namely `a'
In the first argument of `flatten', namely `(List a)'
In the first argument of `(++)', namely `flatten (List a)'
flatten_list.hs:18:69:
Couldn't match type `a' with `NestedList a'
`a' is a rigid type variable bound by
the type signature for
append :: NestedList a
-> NestedList a -> Either String (NestedList a)
at flatten_list.hs:15:9
Expected type: [NestedList (NestedList a)]
Actual type: [NestedList a]
In the first argument of `List', namely `b'
In the first argument of `flatten', namely `(List b)'
In the second argument of `(++)', namely `flatten (List b)'
Upvotes: 0
Views: 431
Reputation: 14598
import Data.Traversable
append :: NestedList a -> NestedList a -> Either String (NestedList a)
append (Elem x) (Elem y) = Right $ List [Elem x, Elem y]
append (Elem _) _ = Left ""
append _ (Elem _) = Left ""
append (List xs) (List ys) = fmap List $ sequenceA $ zipWith append xs ys
The append you wrote in your questions seems to want to just flatten and concatenate the two lists, which is rather pointless, since you are throwing away all the structure. If this is desired behavior, then just use a regular list:
append' :: NestedList a -> NestedList a -> Either String [a]
append' (Elem x) (Elem y) = Right $ [x,y]
append' (Elem _) _ = Left ""
append' _ (Elem _) = Left ""
append' a b = Right $ flatten a ++ flatten b
You could also define your datatype in terms of the free monad:
import Control.Monad.Free
type NestedList = Free []
flatten :: NestedList a -> [a]
flatten = retract
append :: NestedList a -> NestedList a -> Either String (NestedList a)
append (Pure x) (Pure y) = Right $ Free [Pure x, Pure y]
append (Pure _) _ = Left ""
append _ (Pure _) = Left ""
append (Free xs) (Free ys) = fmap Free $ sequenceA $ zipWith append xs ys
This definition is isomorphic to the one you gave.
Upvotes: 1