Fmap поверх списка, содержащего отдельные элементы и списки
У меня есть структура данных, как так
data ShoppingList a
= Empty
| Item a
| Listofitems [ShoppingList a]
deriving (Show)
Я пытаюсь написать Fmap для этого
instance Functor ShoppingList where
fmap f Empty = Empty
fmap f (Item i) = Item (f i)
fmap f (Listofitems [Empty]) = Empty
fmap f (Listofitems ((Item a):Listofitems [as])) = Listofitems $ (fmap f (Item a)) (fmap f Listofitems [as])
Это то, что я написал до сих пор, но оно не компилируется, не могли бы вы помочь мне понять, в чем проблема, объяснение было бы потрясающим. Две ошибки, которые я получаю
src\Ml.hs:19:33: error:
* Couldn't match expected type `[ShoppingList a]'
with actual type `ShoppingList a0'
* In the pattern: Listofitems [as]
In the pattern: (Item a) : Listofitems [as]
In the pattern: Listofitems ((Item a) : Listofitems [as])
* Relevant bindings include
a :: a (bound at src\Ml.hs:19:30)
f :: a -> b (bound at src\Ml.hs:19:8)
fmap :: (a -> b) -> ShoppingList a -> ShoppingList b
(bound at src\Ml.hs:16:3)
|
19 | fmap f (Listofitems ((Item a):Listofitems [as])) = Listofitems $ (fmap f (Item a)) (fmap f Listofitems [as])
| ^^^^^^^^^^^^^^^^
src\Ml.hs:19:68: error:
* Couldn't match expected type `b -> [ShoppingList b]'
with actual type `ShoppingList b'
* The function `fmap' is applied to three arguments,
but its type `(a -> b) -> ShoppingList a -> ShoppingList b'
has only two
In the second argument of `($)', namely
`(fmap f (Item a)) (fmap f Listofitems [as])'
In the expression:
Listofitems $ (fmap f (Item a)) (fmap f Listofitems [as])
* Relevant bindings include
f :: a -> b (bound at src\Ml.hs:19:8)
fmap :: (a -> b) -> ShoppingList a -> ShoppingList b
(bound at src\Ml.hs:16:3)
|
19 | fmap f (Listofitems ((Item a):Listofitems [as])) = Listofitems $ (fmap f (Item a)) (fmap f Listofitems [as])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
В основном, если у меня есть список = [ Item Apple,Empty, [Item Banana,Empty ] ], я хочу, чтобы список fmap (++ M) возвращал [Item AppleM .Empty .[Item BananaM,Empty]]
1 ответ
Обратите внимание на тип данных
Прежде всего, ваш тип данных чрезмерно усложняет. Список предметов действительно должен быть списком, так что вы можете определить data ShoppingList' a = ShoppingList' [a]
в любом случае вы используете списки в вашем. Нет необходимости, чтобы список покупок был вложенным.
Решение вашего вопроса
Если, однако, вам это нужно, это решение. Примечание. Я предположил, что вам не нужен список ShoppingLists, так как в вашем определении данных уже есть список. Так что вы можете позвонить
--fmap :: (a -> b) -> ShoppingList a -> ShoppingList b
fmap _ Empty = Empty
fmap f (Item i) = Item (f i)
fmap f (Listofitems ls) = Listofitems $ map (fmap f) ls
>>fmap (++ "M") $ Listofitems [Item "Apple", Empty, Listofitems [Item "Banana", Empty]]
Listofitems [Item "AppleM",Empty,Listofitems [Item "BananaM",Empty]]
Замечания:
- Вам нужны кавычки вокруг ваших строк,
- Вы должны позвонить по списку
Также помните, что операции добавления строк не эффективны с длинными строками, если вам нужна производительность