当我使用MultiParamTypeClasses时,我可以创建忽略一个类型参数(例如下面的"identity“)的类函数。
{-# LANGUAGE MultiParamTypeClasses #-}
data Add = Add
data Mul = Mul
class Test a b where
identity::a
instance Test Int Add where
identity = 0
instance Test Int Mul where
identity = 1
(这是一个精简的版本,当然在整个程序中还会有其他函数使用"b")。
示例编译,但我永远无法访问标识!
main = do
putStrLn (show (identity::Int))
导致“(Test b0)因使用'identity‘而产生。
有办法获取身份吗?如果不是,编译器不应该禁止我创建一个不使用所有类型参数的类函数吗?
发布于 2013-11-20 11:32:53
如果不是,编译器不应该禁止我创建一个不使用所有类型参数的类函数吗?
也许吧。实际上,您将永远无法使用这样的类方法。但是,由于错误总是发生在编译时,所以并不是很危险。
在某些类似情况下有效的修复(但在您的情况下):
g
元素创建多个实例。identity
的行为依赖于Phantom类型变量。为了达到你的目标,你必须以某种方式传递你想要的实例的信息。实现这一目标的一种方法是虚幻的论点:
class Group_PA g p where
identity :: p -> g
instance Group_PA Int Add where
identity _ = 0
instance Group_PA Int Mult where
identity _ = 1
然后你就可以像这样
GHCi>标识添加::Int 0GHCi>标识Mult ::Int 1
也许更惯用的做法是将标志类型变为空。
{-# LANGUAGE EmptyDataDecls #-}
data Add
data Mult
GHCi>标识(未定义::添加) ::Int 0GHCi>标识(未定义::Mult) ::Int 1
这使我们更加清楚,幻影参数实际上没有运行时信息,只是控制编译器选择哪个实例。
无可否认,这是相当丑陋的。
发布于 2013-11-20 11:22:27
如果使用FlexibleInstances
,则可以更改实例定义,以便可以使用标识:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
data Add = Add
data Mul = Mul
class Test a b where
identity::a
instance Test Int b where
identity = 0
main :: IO ()
main = do
print $ (identity :: Int)
因为实例可以在另一个文件中定义,然后只有该文件才需要使用FlexibleInstances
,所以GHC不能不允许不使用所有类型变量的类声明。
如果您想要不同b's
的实例,那么您必须使用FunctionalDependencies
。
https://stackoverflow.com/questions/20104747
复制相似问题