Построение значения моего собственного типа данных в Haskell

Я пытаюсь создать новое значение типа MyData, который является определенным мной типом персональных данных, но получаю сообщение об ошибке. MyData имеет конструктор List, который получает список значений MyData. Я пытаюсь извлечь два элемента MyData из типа List и создать новый с помощью конструктора Two And. Парсер работает отлично, я проверял.

data MyData = Var String | Con Bool | Two TwoOp MyData MyData | List [MyData] 
 deriving Show
data Final= F MyData MyData deriving Show
data TwoOp = And | Or deriving Show

add_and (Right (F (List e1) (List e2))) i1 i2 = do
 a<-e1!!i1
 b<-e1!!i2
 return (Two And a b)

 val (Right (F e1 e2))=add_and (Right (F e1 e2)) 0 1
 parse_value string_expression= val (parse getfinal "" string_expression)

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

Вот ошибка, которую я получаю:

 Couldn't match type `MyData' with `m MyData'
    Expected type: [m MyData]
      Actual type: [MyData]
    Relevant bindings include
      add_and :: Either t Final -> Int -> Int -> m MyData
        (bound at D:\PF\final.hs:53:1)
    In the first argument of `(!!)', namely `e1'
    In a stmt of a 'do' block: a <- e1 !! i1

D:\PF\final.hs:55:5:
    Couldn't match type `MyData' with `m MyData'
    Expected type: [m MyData]
      Actual type: [MyData]
    Relevant bindings include
      add_and :: Either t Final -> Int -> Int -> MyData
        (bound at D:\PF\final.hs:53:1)
    In the first argument of `(!!)', namely `e1'
    In a stmt of a 'do' block: b <- e1 !! i2
Failed, modules loaded: none.

person vasiliu iorgu    schedule 23.05.2016    source источник
comment
Вы принимаете нотацию do, похоже, что императивное программирование слишком далеко. Сначала вы должны работать с монадическими значениями (т. е. классами, которые являются экземплярами класса типа Monad), прежде чем вы сможете попробовать использовать нотацию do.   -  person chepner    schedule 24.05.2016


Ответы (1)


Вы не хотите использовать <- для извлечения значений из списка.

В этом случае вы просто хотите использовать сопоставление с образцом:

add_and :: Final -> MyData
add_and (F (List (a:_)) (List (b:_))) = Two And a b
add_and _ = error "I don't know what to do here."

list1 :: MyData
list1 = List [ Var "abc" ]

list2 :: MyData  
list2 = List [ Con False ]

final :: Final
final = F list1 list2

main = print $ add_and final

При запуске в ghci:

*Main> main
Two And (Var "abc") (Con False)
person ErikR    schedule 23.05.2016