我的任务是实现这些功能,但我一开始就陷入困境。
为什么我不能这样写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)
答案 0 :(得分:7)
我认为您混淆的根源可能是Catalina base directory
关键字。
忘记所有先入为主的课程概念。 Haskell class
实际上与Java中的面向对象语言中的class
完全不同。类型类更像是Java class
而不是interface
。
更具体地说,Haskell中的class
定义了一个类型可能符合的签名或接口。所以当你写
class
您要声明一类类似地图的类型class MapLike m where
empty :: m k v
lookup :: Ord k => k -> m k v -> Maybe v
,并且为了m :: * -> * -> *
,类型必须至少支持MapLike
和empty
操作。
现在我可以编写适用于任何lookup
类型的函数。
MapLike
类型类的实现进入contains :: (MapLike m, Ord k) => m k v -> k -> Bool
m `contains` k =
case lookup k m of
Just _ -> True
Nothing -> False
。你说你正在实现哪个instance
,你说哪个类型实现了它,然后你给出了在类中声明的函数的实现。所以,在下面,我说class
是ListMap
类型,我正在解释MapLike
和empty
操作如何适用于lookup
类型。
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)
适用于任何contains
类型,MapLike
是ListMap
的实例,我们可以MapLike
使用contains
ListMap
面向对象的类对对象进行分类,而类型类对类进行分类。我确实认为单词ghci> let myMap = ListMap [("foo", 'a'), ("bar", b)]
ghci> myMap `contains` "foo"
True
ghci> myMap `contains` "nabble"
False
和class
是不幸的 - 它们让具有OO背景的新人感到困惑 - 但是Haskell早于OOP变得流行,所以语言设计者不知道。 Idris,Haskell家族中的一种新语言,也有类型类,但they're called interface
s,我认为这是一个更好的名称。