是否可以对类更高的类型的类实例强制执行类型约束?

问题描述 投票:3回答:2

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

newtype PrimeSet a = P Integer
    deriving Eq

我还定义了一个函数,它将一个素数集转换为一个列表,因为它的类型参数是一个Integral

toList :: Integral a => PrimeSet a -> [a]

我现在该怎么给PrimeSet一个Foldable实例,所以这是我的第一次尝试(从fold导入Data.Foldable之后):

instance Foldable PrimeSet where
    foldMap f = fold . map f . toList

然而,这不起作用,编译器告诉我它Could not deduce (Integral a) arising from a use of ‘toList’。我对这个消息的理解是toList要求它的参数是Integral a => PrimeSet a类型,但在Foldable实例中不一定是这种情况。

该消息还说可能的修复方法是将Integral a添加到我的foldMap实现的类型签名的上下文中,但当然我被告知我不允许为类方法提供我自己的类型定义,除非我使用InstanceSigs,所以我试过了,但这似乎也没有用。

所以我的问题是:如果我正在编写类实例的类型的类型参数被隐藏,是否可以向类实例添加类型约束 - 或者,重申一下,我可以这样做吗?

instance (Integral a) => Foldable (PrimeSet a) where

(这当然不起作用,因为PrimeSet a有类*Foldable需要* -> *

haskell typeclass type-constraints higher-kinded-types
2个回答
3
投票

不,这是不可能的。高等级类型的重点是处理任何参数类型。而PrimeSet根本不是真正的参数 - 基本上,它始终是PrimeSet Integer。为什么你有这个a参数?

然而,对于“有点容器”的类型有一个不同的类,但不是任意类型:MonoTraversable,或者在这种情况下实际上是MonoFoldable

{-# 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。我有这样一个类in my constrained-categories package。但是,特别是对于这种类型,这似乎没有任何意义。


2
投票

您可以使用GADT来约束参数类型:

{-# LANGUAGE GADTs #-}

data PrimeSet a where
    PrimeSet :: Integral a => Integer -> PrimeSet a

instance Foldable PrimeSet where
    foldr f b (PrimeSet x) = f (fromInteger x) b

你可以用ConstraintKinds(和monofoldable类)来概括一点:

data Monomorphic f c a where
    Monomorphic :: c a => f -> Monomorphic f c a

instance (item ~ Item f, MonoFoldable f) => Foldable (Monomorphic f ((~) item)) where
    foldr f b (Monomorphic xs) = ofoldr f b xs

data PrimeSet = PrimeSet Integer

instance Foldable (Monomorphic PrimeSet Integral) where
    foldr f b (Monomorphic (PrimeSet i)) = f (fromInteger i) b
© www.soinside.com 2019 - 2024. All rights reserved.