我想定义一个函数<-?
来检查元素是否在列表/集合/映射中。
module Test where
import qualified Data.Map as Map
import qualified Data.Set as Set
class Memberable a where
(<-?) :: b -> a -> Bool
instance Memberable [x] where
(<-?) = elem
instance Memberable (Map.Map k v) where
(<-?) = Map.member
instance Memberable (Set.Set x) where
(<-?) = Set.member
类声明中的类型变量b
应该是我想要检查的元素的类型。但是,这对Haskell不起作用。
Test.hs:8:13:
Couldn't match type 'b' with 'x'
'b' is a rigid type variable bound by
the type signature for (<-?) :: b -> [x] -> Bool at Test.hs:8:5
'x' is a rigid type variable bound by
the instance declaration at Test.hs:7:10
Expected type: b -> [x] -> Bool
Actual type: b -> [b] -> Bool
Relevant bindings include
(<-?) :: b -> [x] -> Bool (bound at Test.hs:8:5)
In the expression: elem
In an equation for '<-?': (<-?) = elem
如何在类声明中使用b
,但仍然使类型重合?
答案 0 :(得分:9)
TypeFamilies
问题是你必须以某种方式将b
与你的集合(其中的元素)联系起来 - 有几种方法可以做到这一点,但我认为一个相当不错的方法是使用TypeFamilies:< / p>
{-# LANGUAGE TypeFamilies #-}
module Test where
import qualified Data.Map as Map
import qualified Data.Set as Set
class Memberable a where
type ElemT a :: *
(<-?) :: (ElemT a) -> a -> Bool
instance Eq x => Memberable [x] where
type ElemT [x] = x
(<-?) = elem
instance Ord k => Memberable (Map.Map k v) where
type ElemT (Map.Map k v) = k
(<-?) = Map.member
instance Ord x => Memberable (Set.Set x) where
type ElemT (Set.Set x) = x
(<-?) = Set.member
正如您所看到的,我在类中添加了一个type
成员,其中包含所使用元素的类型(因此您可以将它们用于(<-?)
下一行)。
我还为您的实例添加了所需的约束 - 这些约束确实来自elem
,Map.member
和Set.member
等已使用的函数。
MultiParamTypeClasses
这是@dfeuer暗示的(或者我认为):
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Test where
import qualified Data.Map as Map
import qualified Data.Set as Set
class Memberable e a where
(<-?) :: e -> a -> Bool
instance Eq x => Memberable x [x] where
(<-?) = elem
instance Ord k => Memberable k (Map.Map k v) where
(<-?) = Map.member
instance Ord x => Memberable x (Set.Set x) where
(<-?) = Set.member
我认为使用这种方法你也可能想要添加这个FunctionalDependency
,因为你明确地在集合a
和它的元素e
之间存在这样的依赖关系; )
{-# LANGUAGE FunctionalDependencies #-}
class Memberable e a | a -> e where
(<-?) :: e -> a -> Bool