功能依赖/类型系列

are*_*enl 2 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
Run Code Online (Sandbox Code Playgroud)

一切都会很完美.

> f (1 :: Int)
1
> f (1.9 :: Float)
1
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试写类似的东西

instance F Double String where
  f = show
Run Code Online (Sandbox Code Playgroud)

我将得到以下编译错误:

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'
Run Code Online (Sandbox Code Playgroud)

有没有办法用类型系列而不是fundeps来解决这个问题?

Joh*_*n L 12

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

class (Num a, Integral b) => F a b
Run Code Online (Sandbox Code Playgroud)

声明必须有一个Integral实例b.A String没有Integral实例,因此F a String除非您定义,否则您不能拥有任何形式

-- String is a type synonym for [Char]
instance Integral [Char] where
Run Code Online (Sandbox Code Playgroud)

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

  • 我把你的问题解释为"这不能编译,我能用AT而不是FunDeps编译吗?".带有字符串/编译器错误的部分完全不相关,如果你把它拿出来可能会更清楚.由于您在fundep版本中包含了超类约束,因此很明显任何AT解决方案都需要考虑它们. (5认同)
  • 但你不能**希望**约束它,同时**想要**不满足约束的F实例!穷人编译器应该做什么?做一个例外,因为这是你吗? (4认同)

fuz*_*fuz 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
Run Code Online (Sandbox Code Playgroud)

此示例不直接使用类型系列,而是使用相同的标志激活的关联类型同义词.这个想法很简单.我们定义了一个类型的同义词,而不是明确给出类型类的第二个参数,并用适当的类型填充.

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