我的任务是实现这些功能,但我先陷入困境.
为什么我不能这样写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)
我认为你的困惑的根源可能是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一个类型必须至少支持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
Run Code Online (Sandbox Code Playgroud)
类型类的实现在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)
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)
面向对象的类对对象进行分类,而类型类对类进行分类.我想的话class和instance不恰当-他们混淆新人与面向对象的背景-但哈斯克尔早OOP成为受欢迎的,所以语言设计师们不知道.Idris是Haskell家族中的一种新语言,也有类型类,但它们被称为interfaces,我认为这是一个更好的名称.