Haskell Либо String (NestedList a) - почему он не работает

Я пытаюсь добавить функцию, которая работает с вложенными списками, как обычные списки. Я хочу использовать любую строку (вложенную), чтобы она возвращала ошибку или добавленный список. Но он продолжает терпеть неудачу. Я не делаю NestedList [NestedList a] где угодно. Почему он говорит, что ожидается [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 ]] ))

дает мне эту ошибку

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)'
1 ответ

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

Добавление, которое вы писали в ваших вопросах, похоже, просто сглаживает и объединяет два списка, что довольно бессмысленно, поскольку вы выбрасываете всю структуру. Если это желаемое поведение, просто используйте обычный список:

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

Вы также можете определить свой тип данных с точки зрения свободной монады:

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

Это определение изоморфно тому, которое вы дали.

licensed under cc by-sa 3.0 with attribution.