使用函数依赖项,我可以使用多参数类型类约束类型类中的依赖参数类型.像这样:
{-# 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包装并为其创建实例.
我想你想要这样的东西:
{-# 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)
此示例不直接使用类型系列,而是使用相同的标志激活的关联类型同义词.这个想法很简单.我们定义了一个类型的同义词,而不是明确给出类型类的第二个参数,并用适当的类型填充.
这也是我第一次使用关联类型同义词,但它似乎是一个非常酷的功能.