直接在Haskell类中定义一个空容器?

Ole*_*leg 1 haskell typeclass

我的任务是实现这些功能,但我先陷入困境.

为什么我不能这样写empty?(ghci抱怨:couldn't match type)

我不是说那[]应该是type m k v吗?

class MapLike m where
    empty :: m k v
    empty = [] :: m k v
    lookup :: Ord k => k -> m k v -> Maybe v

newtype ListMap k v = ListMap { getListMap :: [(k,v)] } deriving (Eq,Show)
Run Code Online (Sandbox Code Playgroud)

Ben*_*son 7

我认为你的困惑的根源可能是class关键字.

忘记所有先入为主的课程概念.Haskell class实际上并不class像Java这样的面向对象语言.类型类更像是Java而interface不是class.

更具体地说,classHaskell中的a定义了类型可以符合的签名接口.所以当你写作

class MapLike m where
    empty :: m k v
    lookup :: Ord k => k -> m k v -> Maybe v
Run Code Online (Sandbox Code Playgroud)

你宣布了​​一类类似地图的类型m :: * -> * -> *,并且为了成为MapLike一个类型必须至少支持emptylookup操作.

现在我可以编写适用于任何MapLike类型的函数.

contains :: (MapLike m, Ord k) => m k v -> k -> Bool
m `contains` k =
    case lookup k m of
        Just _ -> True
        Nothing -> False
Run Code Online (Sandbox Code Playgroud)

类型类的实现instance.你说class你正在实现哪个,你说哪个类型实现它,然后你给类中声明的函数实现.所以,下面,我说这ListMap是一种MapLike类型,我正在解释emptylookup操作如何适用于该ListMap类型.

instance MapLike ListMap where
    empty = ListMap []
    lookup k (ListMap []) = Nothing
    lookup k (ListMap ((k', v):kvs)
        | k == k' = Just v
        | otherwise = lookup k (ListMap kvs)
Run Code Online (Sandbox Code Playgroud)

由于contains适用于任何MapLike类型的,并且ListMap是的一个实例MapLike,我们可以使用contains一个ListMap.

ghci> let myMap = ListMap [("foo", 'a'), ("bar", b)]
ghci> myMap `contains` "foo"
True
ghci> myMap `contains` "nabble"
False
Run Code Online (Sandbox Code Playgroud)

面向对象的类对对象进行分类,而类型类对类进行分类.我想的话classinstance不恰当-他们混淆新人与面向对象的背景-但哈斯克尔早OOP成为受欢迎的,所以语言设计师们不知道.Idris是Haskell家族中的一种新语言,也有类型类,但它们被称为interfaces,我认为这是一个更好的名称.