问题描述
我有一个这样定义的类型:
I have a type defined like this:
newtype PrimeSet a = P Integer
deriving Eq
我还定义了一个将素数集转换为列表的函数,因为它的类型参数是一个 Integral
.
I have also defined a function which converts a prime set to a list, given that its type parameter is an Integral
.
toList :: Integral a => PrimeSet a -> [a]
我现在要给 PrimeSet
一个 Foldable
实例,所以这是我的第一次尝试(在从 Data.可折叠
):
I now what to give PrimeSet
a Foldable
instance, so this was my first attempt (after importing fold
from Data.Foldable
):
instance Foldable PrimeSet where
foldMap f = fold . map f . toList
然而,这不起作用,编译器告诉我它无法推导出使用‘toList’产生的(积分 a)
.我对这条消息的理解是 toList
要求它的参数是一个 Integral a =>PrimeSet a
类型,但在 Foldable
实例中不一定是这种情况.
This didn't work, however, and the compiler told me that it Could not deduce (Integral a) arising from a use of ‘toList’
. My understanding of this message is that toList
requires its argument to be an Integral a => PrimeSet a
type, but this isn't necessarily the case in the Foldable
instance.
该消息还说,一个可能的解决方法是将 Integral a
添加到我的 foldMap
实现的类型签名的上下文中,但当然我被告知除非我使用 InstanceSigs
,否则我不允许为类方法提供我自己的类型定义,所以我尝试过,但似乎也不起作用.
The message also said that a possible fix would be to add Integral a
to the context of the type signature for my foldMap
implementation, but of course I was then told that I'm not allowed to provide my own type definitons for class methods unless I use InstanceSigs
, so I tried that but that didn't seem to work either.
所以我的问题是:如果我正在为其编写类实例的类型的类型参数被隐藏,是否可以向类实例添加类型约束 - 或者重申一下,我可以做这样的事情吗??
So my question is this: is it possible to add a type constraint to a class instance if the type parameter of the type I'm writing the class instance for is hidden - or, to reiterate, can I do something like this?
instance (Integral a) => Foldable (PrimeSet a) where
(这当然不起作用,因为 PrimeSet a
具有 *
类型,而 Foldable
需要 * -> *
)
(This of course doesn't work because PrimeSet a
has the kind *
whereas Foldable
requires * -> *
)
推荐答案
不,这是不可能的.高级类型的全部意义在于处理任何参数类型.而 PrimeSet
根本就不是参数——基本上,它是总是 PrimeSet Integer
.为什么你有那个 a
参数?
No, this is not possible. The whole point of higher-kinded types is to work over any parameter type. Whereas PrimeSet
isn't really parametric at all – basically, it's always PrimeSet Integer
. Why do you have that a
parameter at all?
然而,对于有点容器"的类型有一个不同的类,但不适用于任意类型:MonoTraversable,或者实际上 MonoFoldable.
There is however a different class for types that are "kinda containers", but not for arbitrary types: MonoTraversable, or actually MonoFoldable in this case.
{-# LANGUAGE FlexibleInstances, TypeFamilies #-}
import Data.MonoTraversable
type instance Element (PrimeSet a) = a
-- or, if `PrimeSet` is not parameterised,
-- type instance Element PrimeSet = Integer
instance (Integral a) => MonoFoldable (PrimeSet a) where
otoList = YourImplementation.toList
另一种选择是您确实使用参数化类型,实际上是函子,但不在所有 Haskell 类型的正常Hask 类别中,而仅在其类型的子类别中 是 Integer
.我有这样一个类 在我的约束-类别包.但是,尤其是对于您拥有的这种类型,这似乎真的没有任何意义.
An alternative would be that you do use parameterised types, functors in fact, but not in the normal Hask category of all Haskell types but only in the subcategory whose type is Integer
. I have such a class in my constrained-categories package. But, especially for this type you have, this really doesn't seem to make any sense.
这篇关于是否可以对更高级的类型的类实例强制执行类型约束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!