Работа с пользовательским типом данных haskell

У меня есть этот тип данных data List x = LT [(x,[String])], и я пытаюсь создать функцию, которая добавит новый элемент в List.

Например, используя функцию add:

add ('a', ["1","2"]) [('x',["1"])]

результатом будет:

[('x',["1"]), ('a', ["1","2"])]

Неважно, какой порядок. Я много пробовал, до сих пор многого не понимаю.

Это то, что я пробовал

`add:: Ord a => a -> List a -> List a 
 add _ (LT[]) = empty 
 add x (LT(y:ys))
     | belongs x (LT(y:ys)) = (LT(y:ys)) 
     | otherwise = (LT(y:ys)) ++ (LT(x))`

Кто-нибудь может помочь? Заранее спасибо.


person Francisco Costa    schedule 24.11.2016    source источник
comment
Не могли бы вы просто использовать ++? Вы уже используете список Haskell в своем определении, поэтому, если вы указали ('a', ["1","2"]) в качестве списка, например. [('a', ["1","2"])], тогда ваша функция может просто взять два списка, использовать ++ и вернуть новый список, который будет содержать оба. hackage.haskell.org/package/base-4.9. 0.0/docs/Data-List.html   -  person Danny Wilson    schedule 24.11.2016
comment
@DannyWilson, извините, наверное, я не правильно сформулировал вопрос, функция добавления получает элемент и список (LT), а не совсем кортеж и список, поэтому ++ не работает.   -  person Francisco Costa    schedule 24.11.2016
comment
Тогда ваш пример должен быть add 'a' [('x', ["1"])]. Однако неясно, какой список должен быть связан с 'a' в результате. Это просто тот же список, связанный с предыдущим последним значением, но с добавлением в конец еще одной числовой строки?   -  person chepner    schedule 24.11.2016


Ответы (1)


Как указал Дэнни Уилсон, вы можете использовать оператор ++ для объединения двух списков:

ghci> [1,2] ++ [3,4]
[1,2,3,4]

Имейте в виду, что обе стороны ++ должны быть списками, и у вас есть один список и один не-список, поэтому вам нужно сначала превратить один из них в список.

У меня есть дикое предположение, основанное на некоторых деталях вашей формулировки, что у вас проблемы с конструкторами данных. List x не принимает форму

[('x',["1"])]

Скорее

LT [('x',["1"])]

который представляет собой обычный список, "обернутый" LT конструктором. Если вы хотите написать функцию add, вам нужно выполнить сопоставление с образцом в этом конструкторе. Каждое значение типа List "начинается с" LT:

add :: (x, [String]) -> List x -> List x
add elem (LT list) = LT (...)

(Вам нужно заполнить ... самостоятельно)

Вам нужно только поставить LT, когда вам нужно получить доступ к кишкам типа, список внутри. Таким образом, эта функция возвращает список без изменений, и LT ей не требуется:

doNothing :: List x -> List x
doNothing a = a

Но как только вам нужно знать, что List x представлен списком каких-то вещей, вам нужно использовать конструктор LT.

Это помогает?

person luqui    schedule 24.11.2016
comment
Это как бы работает, вот что я пытался сделать add:: Ord a => a -> List a -> List a add _ (LT[]) = empty add x (LT(y:ys)) | belongs x (LT(y:ys)) = (LT(y:ys)) | otherwise = (LT(y:ys)) ++ (LT(x)) Но это не работает (belongs и empty две функции, которые я сделал). - person Francisco Costa; 24.11.2016
comment
Да, в LT(x) есть ошибка типа, потому что x не является списком. Попробуйте LT [x] (сначала превратите его в список из одного элемента, и нам никогда не нужны были круглые скобки). Обратите внимание, что способ, которым это указано, добавление чего-либо в пустой список всегда будет пустым, что... не совсем правильно. Но вашей первой целью должно быть заставить его компилироваться без ошибок типов. - person luqui; 24.11.2016
comment
О, есть еще одна ошибка типа, когда вы говорите (LT ...) ++ (LT ...). ++ принимает два списка haskell, а не два ваших List (которые созданы с помощью LT). Вам нужно поместить ++ внутри конструктора LT. - person luqui; 24.11.2016
comment
Нравится (LT (y:ys) ++ x)?? - person Francisco Costa; 24.11.2016
comment
LT ((y:ys) ++ [x]). Применение функции (что делает LT) сложнее, чем любой другой оператор, поэтому оно применяется только к части (y:ys), а не к части ++ x. И нам нужно было сделать одноэлементный список из x, как я постоянно говорю - person luqui; 24.11.2016
comment
Все еще не работает... вот что показывает Couldn't match expected type ‘[(a, [String])]’ with actual type ‘a’. - person Francisco Costa; 24.11.2016
comment
Да, ваша подпись типа неверна. Вы, кажется, понятия не имеете, что делаете, вы просто пробуете что-то наугад. Вернитесь к более раннему учебнику (например, LYAH) или обратитесь за помощью к преподавателю, если вы находитесь на занятии. Эта проблема в настоящее время слишком сложна для вас. - person luqui; 24.11.2016
comment
Да, я пытался понять это с помощью этой книги Learnyouahaskell.com, но дело дошло до случайных попыток, подпись типа была дана профессором в качестве типа данных, просто хотел понять, как это работает с типами данных и как Я могу получить доступ к элементам в нем. Но все равно спасибо. - person Francisco Costa; 24.11.2016
comment
Просто чтобы прояснить ситуацию, ваш тип данных и подпись типа — это очень разные вещи. Ваш тип данных — data List x = LT [(x,[String])], который определяет данные, которые вы хотите обработать, вроде объекта в OO. Думайте об этом так: у вас есть тип данных data Circle = Float Float Float, который определяет круг с 3 значениями с плавающей запятой. Затем, когда вы хотите работать с ним, вы пишете функцию. Первая строка — определение типа. Так, например, addInts :: Int -> Int -> Int, который принимает два целых числа и возвращает целое число. Если вы не уверены в типе, оставьте строку... - person Danny Wilson; 24.11.2016
comment
Пусть Haskell угадывает, что в большинстве случаев он сможет. Это избавит вас от вашей ошибки, затем вызовите :t addInts, и он сообщит вам сигнатуру типа addInt :: Int -> Int -> Int. - person Danny Wilson; 24.11.2016