在实例声明中键入约束但不在类中键入

时间:2018-03-10 21:06:40

标签: haskell

我想创建一个具有类型约束的函数定义的实例,但我不想将类型约束添加到类中。

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

1 个答案:

答案 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