繁体   English   中英

Haskell 结合多个类型类约束

[英]Haskell combine multiple typeclass constraints

{-# LANGUAGE TypeFamilies #-}

import GHC.Prim
import qualified Data.Set as Set

class Functor' f where
    type FConstraint f :: * -> Constraint
    fmap' :: (FConstraint f a, FConstraint f b) => (a -> b) -> f a -> f b

instance Functor' Set.Set where
    type FConstraint Set.Set = Ord Num  --error here, won't let me put Num
    fmap' = Set.map

我想知道如何才能使上述工作。 现在我知道我可以手动需要两个类型类,但我希望能够组合任意数量的它们。

现在我知道在这种情况下要求Num没有意义,但这纯粹是一个例子。

您将需要定义一个类型类(因为可以部分应用类型类),它通过超类减少到您想要的约束:

{-# LANGUAGE 
    PolyKinds, UndecidableInstances, TypeOperators
  , MultiParamTypeClasses, ConstraintKinds, TypeFamilies
  , FlexibleContexts, FlexibleInstances 
#-}

class (f x, g x) => (&) f g (x :: k)
instance (f x, g x) => (&) f g x

显然(f & g) x成立 iff fxgx成立。 FConstraint'的定义现在应该很明显了:

class Functor' ... 

instance Functor' Set.Set where
    type FConstraint Set.Set = Ord & Num
    fmap' f = Set.map ( (+1) . f )  -- (+1) to actually use the Num constraint

看起来我需要做的唯一改变不是部分应用FConstraint

{-# LANGUAGE TypeFamilies #-}

import GHC.Prim
import qualified Data.Set as Set

class Functor' f where
    type FConstraint f a :: Constraint
    fmap' :: (FConstraint f a, FConstraint f b) => (a -> b) -> f a -> f b 

instance Functor' Set.Set where
    type FConstraint Set.Set a = (Ord a, Num a)
    fmap' f = Set.map ((+ 1) . f)

foo = fmap (+ 1) $ Set.fromList [1, 2, 3]

不幸的是,据我所知,这不允许我使用具体类型,但我想这甚至不会在种类级别上与 Functor 匹配( Functor有种类* -> *但具体值的列表,例如String有种类* )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM