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
成立当且仅当 f x
和 g x
成立。 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
有种类 *
).
{-# 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
成立当且仅当 f x
和 g x
成立。 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
有种类 *
).