当A类为B类提供足够的信息时,B的Gen实例是Haskell [英] Haskell, Gen instance of B when class A provides enough info for class B

查看:101
本文介绍了当A类为B类提供足够的信息时,B的Gen实例是Haskell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为集合/容器类型编写类时(顺便说一下,如果我重新发明轮子,则指向现有类型)提供一个通用接口,用于添加和删除任何集合类型的元素。

  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
基础库的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆