功能依赖/类型系列

时间:2011-04-11 16:27:52

标签: haskell types

对于函数依赖项,我可以使用多参数类型类约束类型类中的依赖参数类型。就像这样:

{-# LANGUAGE FunctionalDependencies, MultiParamTypeClasses,TypeSynonymInstances  #-}

class (Num a, Integral b) => F a b | a -> b where
  f :: a -> b

instance F Int Int where
  f = id

instance F Float Integer where
  f = truncate

一切都会完美无缺。

> f (1 :: Int)
1
> f (1.9 :: Float)
1

但如果我尝试写类似

的东西
instance F Double String where
  f = show

我将收到以下编译错误:

No instance for (Integral String)
arising from the superclasses of an instance declaration
Possible fix: add an instance declaration for (Integral String)
In the instance declaration for `F Double String'

有没有办法用类型系列代替fundeps?

2 个答案:

答案 0 :(得分:12)

基本上没有,这实际上与功能依赖(或类型系列)无关。你的班级定义有

class (Num a, Integral b) => F a b

声明必须有b的Integral实例。 String没有Integral实例,因此除非您定义

,否则您不能拥有F a String形式的任何内容
-- String is a type synonym for [Char]
instance Integral [Char] where

我不知道这一般是明智的。如果在系统中为字符串创建一个Integral实例是有意义的,那么您可能希望在String周围放置一个newtype包装并为其创建实例。

答案 1 :(得分:5)

我想你想要这样的东西:

{-# LANGUAGE TypeFamilies, FlexibleContexts  #-}
class Num a => G a where
  type B a
  g :: (Integral (B a)) => a -> B a

instance G Int where
  type B Int = Int
  g = id

instance G Float where
  type B Float = Integer
  g = truncate

此示例不是直接使用类型系列,而是关联类型同义词,它由同一个标志激活。这个想法很简单。我们定义了一个类型同义词,而不是为类型类显式提供第二个参数,而是用适当的类型填充。

这也是我第一次使用关联类型同义词,但它似乎是一个非常酷的功能。