Haskell 包含单个元素和列表的列表上的Fmap

Haskell 包含单个元素和列表的列表上的Fmap,haskell,compiler-errors,functor,type-mismatch,algebraic-data-types,Haskell,Compiler Errors,Functor,Type Mismatch,Algebraic Data Types,我有一个这样的数据结构 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

我有一个这样的数据结构

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])
   |                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
基本上如果我有一个列表=[苹果项目,空,[香蕉项目,空]] 我希望fmap(++M)列表返回[Item AppleM.Empty.[Item BananaM,Empty]]

关于数据类型的注释 首先,您的数据类型过于复杂。项目列表实际上应该是一个列表,因此您可以定义
data ShoppingList'A=ShoppingList'[A]
,因为您正在使用列表。没有必要将购物清单嵌套起来

你问题的解决办法 但是,如果您需要这样做,这是一个解决方案。注意:我假设您不需要ShoppingList列表,因为您的数据定义中已经有一个列表。所以你可以打电话

--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]]
注:

  • 字符串周围需要引号
  • 你需要在项目列表中调用它

还要记住,如果需要性能,字符串附加操作对于长字符串是无效的

ShoppingList
看起来已经太复杂了。如果您只需要一个项目列表,请使用
newtype ShoppingList a=SL[a]
。无需将空列表和单例列表表示为单独的项目,您的
Listofitems
允许您构建项目树,而不仅仅是列表。这样,
Functor
实例就变成了
fmap f(SL list)=SL(fmap f list)
“但它不是编译的”–那么你把你得到的错误贴出来怎么样?@chepner,我只是想用一个fmap来练习一些困难的问题