是否可以对更高级的类型的类实例强制执行类型约束? [英] Is it possible to enforce a type constraint on a class instance for a higher-kinded type?

查看:31
本文介绍了是否可以对更高级的类型的类实例强制执行类型约束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样定义的类型:

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 类别中,而仅在其类型的子类别中s areInteger.我有这样一个类 在我的约束-类别包.但是,尤其是对于您拥有的这种类型,这似乎真的没有任何意义.

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 types areis 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.

这篇关于是否可以对更高级的类型的类实例强制执行类型约束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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