当A类为B类提供足够的信息时,B的Gen实例是Haskell [英] Haskell, Gen instance of B when class A provides enough info for class B
问题描述
class(Eq(c a),Monoid(c a))=>集合c a其中
emptyColl :: c a - > Bool
splitColl :: c a - > (a,c a)
toColl :: a - > c a
size :: c a - > Int
combineColl :: a - > c a - > c a
(> |<):: a - > c a - > c a
a> |< c = combineColl a c
我注意到Collection的实例也可以是Foldable的实例。使用splitColl和emptyColl。所以你不需要写一个Foldable,如果你在几个类上构造这样的构造,大量的时间,写出不重要的实例,都可以被保存。
我试图让Collection成为Foldable的一个实例。然而,类似乎不能从其他类实例化吗?
我收到了以下错误消息:
pre $ c $ instance $ Functor(Collection c)其中
'Functor'的第一个参数应该是'* - > *',
,但'集合c'有种'* - > GHC.Prim.Constraint'
在'Functor(Collection c)'的实例声明中
实例Functor(Collection ca)其中
' Functor'应该有种'* - > *',
但'Collection c a'有种'GHC.Prim.Constraint'
在'Functor(Collection ca)'的实例声明中
我如何获得所需的功能?我认为模板Haskell可能会成为这里的一种方式,我从来没有用过它,例如:)
预先感谢!
PS:我一直在写haskell大约一年,想到的小技巧非常值得赞赏
这个标准的技巧是给予适当功能的实现并让用户编写他们自己的实例。例如,你可能写了:
fmapColl ::(Collection c a,Collection c b)=> (a - > b) - > c a - > c b
fmapColl f ca
| emptyColl ca = mkEmptyColl - 你的课没有这个,但可能应该是
|否则= case splitColl ca of
(a,ca') - > f a> |<假设我们有一个合适的类型,比如 CFunctor
: 类CFunctor f其中
类型ConstraintI f
类型ConstraintO f
cfmap ::(ConstraintI i,ConstraintO o)=> (i - > o) - > f i - > fo
然后对于给定的集合
实例 Set
我们可以使用最小的实际代码来实例化 CFunctor
:
实例CFunctor Set其中
类型ConstraintI Set = Ord
类型ConstraintO Set = Ord
cfmap = fmapColl
$ c $你可以看到这个模式 - 为用户定义一个默认实现,将其放入他们的实例中 - 基础库的 fmapDefault
,例如。
While writing a class for a Collection/Container type (btw point me towards existing types if i'm reinventing the wheel) to provide a general interface for adding and removing elements from any 'Collection' type.
class (Eq (c a), Monoid (c a)) => Collection c a where
emptyColl :: c a -> Bool
splitColl :: c a -> (a, c a)
toColl :: a -> c a
size :: c a -> Int
combineColl :: a -> c a -> c a
(>|<) :: a -> c a -> c a
a >|< c = combineColl a c
I noticed instances of Collection could also be instances of Foldable. Using splitColl and emptyColl. So you don't need to write a Foldable as well, if you make constructs like this over several classes a significant amount of time, writing trivial instances, can be saved.
I tried to make Collection an instance of Foldable. However classes can't seem to be instantiated from other classes do they?
I received the following error messages:
instance Functor (Collection c) where
The first argument of ‘Functor’ should have kind ‘* -> *’,
but ‘Collection c’ has kind ‘* -> GHC.Prim.Constraint’
In the instance declaration for ‘Functor (Collection c)’
instance Functor (Collection c a) where
The first argument of ‘Functor’ should have kind ‘* -> *’,
but ‘Collection c a’ has kind ‘GHC.Prim.Constraint’
In the instance declaration for ‘Functor (Collection c a)’
How could I get the desired functionality? I think template Haskell might be the way to go here, I never used it tho, an example would be great :)
Thanks in advance!
PS: I've been writing haskell for about a year, minor tips that come to mind are much appreciated
解决方案 The standard trick for this is to give implementations of the appropriate functions and let users write their own instances. For example, you might write
fmapColl :: (Collection c a, Collection c b) => (a -> b) -> c a -> c b
fmapColl f ca
| emptyColl ca = mkEmptyColl -- you don't have this in your class, but probably should
| otherwise = case splitColl ca of
(a, ca') -> f a >|< fmapColl f ca'
Assuming we had a suitable type class, say, CFunctor
:
class CFunctor f where
type ConstraintI f
type ConstraintO f
cfmap :: (ConstraintI i, ConstraintO o) => (i -> o) -> f i -> f o
Then for a given Collection
instance like Set
we could instantiate CFunctor
with minimal actual code like this:
instance CFunctor Set where
type ConstraintI Set = Ord
type ConstraintO Set = Ord
cfmap = fmapColl
You can see this pattern -- defining a "default" implementation for users to put in their instances -- in the base library's fmapDefault
, for example.
这篇关于当A类为B类提供足够的信息时,B的Gen实例是Haskell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!