我想创建一个具有类型约束的函数定义的实例,但我不想将类型约束添加到类中。
class Foo a where
f :: a b -> b
instance Foo Maybe where
f = fMaybe
fMaybe :: (Num a) => Maybe a -> a
fMaybe (Just i) = i+i
fMaybe _ = 0
如何指定这是包含Maybe
的{{1}}的实例?
这有效:
Nums
但我不想为每种{-# LANGUAGE MultiParamTypeClasses #-}
class Foo a b where
f :: a b -> b
instance Foo Maybe Int where
f = fMaybe
fMaybe :: (Num a) => Maybe a -> a
fMaybe (Just i) = i+i
fMaybe _ = 0
我试过了:
Num
但是我收到了错误:
class Foo a where f :: a -> b instance (Num b) => Foo (Maybe b) where f = fMaybe fMaybe :: (Num a) => Maybe a -> a fMaybe (Just i) = i+i fMaybe _ = 0
答案 0 :(得分:6)
如果不改变类或类型,则无法实现。
MultiParamTypeClasses
方法实际上并不要求您为所有Num
类型编写单独的实例 - 以下工作:
class Foo a b where
f :: a b -> b
instance (Num b) => Foo Maybe b where
f = fMaybe
尽管如此,我并不认为这是一个特别好的方法。
您可以使用ConstraintKinds
允许每个实例有选择地约束所包含的类型。
{-# LANGAUGE TypeFamilies, ConstraintKinds #-}
import GHC.Exts (Constraint)
class Foo a where
type FooCstrt a b :: Constraint
type FooCstrt a b = () -- default to unconstrained
f :: FooCstrt a b => a b -> b
instance Foo Maybe where
type FooCstrt Maybe b = Num b
f = fMaybe
您可以切换到仅允许包含Num
类型的类型。
{-# LANGUAGE GADTs #-}
data NMaybe where
NJust :: Num b => b -> NMaybe b
NNothing :: Num b => NMaybe b
然后,
class Foo a where
f :: a b -> b
instance Foo NMaybe where
f (NJust i) = i+1
f (NNothing) = 0