为什么我不能这样写:
data Color = R | G | B deriving Show
showColor :: Show Color
showColor = Show Color
main = do
putStrLn (showColor.show R)
putStrLn (showColor.show G)
Run Code Online (Sandbox Code Playgroud)
为什么类的实例不是Haskell中的一等公民?
很难讨论为什么语言的某个特征是这样的,因为只有语言的设计者才能真正回答这个问题.然而,他们确定每个类型每个类最多只能有一个实例.这很可能是因为实例是隐含使用的.考虑一堂课
class Foo a where foo :: a -> String
Run Code Online (Sandbox Code Playgroud)
和这个模块
import A -- defines an instance Foo Int
bar :: Int -> String
bar n = "The number is " ++ foo n
Run Code Online (Sandbox Code Playgroud)
该bar函数隐式引用模块A的实例.现在假设我们添加另一个导入
import A -- defines an instance Foo Int
import B -- defines another instance Foo Int
bar :: Int -> String
bar n = "The number is " ++ foo n
Run Code Online (Sandbox Code Playgroud)
现在这是模棱两可的.Haskell可能提供了一种语法来消除歧义,但却选择了禁止它.一个优点是,无论谁读取代码都可以更容易地找到所使用的实例,因为只能有一个.
但是,可以部分模拟多个实例.GHC扩展允许定义隐式参数,允许在每个函数调用时为这些参数指定不同的"实例":
{-# LANGUAGE ImplicitParams #-}
data Color = R | G | B
showColor :: (?showC :: Color -> String) => Color -> String
showColor c = "The color is: " ++ ?showC c
main :: IO ()
main = do
let ?showC = \c -> case c of R -> "Red" ; _ -> "Not Red"
in putStrLn (showColor B)
let ?showC = \c -> case c of G -> "Green" ; _ -> "Not Green"
in putStrLn (showColor B)
Run Code Online (Sandbox Code Playgroud)
以上的输出是:
The color is: Not Red
The color is: Not Green
Run Code Online (Sandbox Code Playgroud)
Agda编程语言没有类型类,但具有扮演类似角色的隐式实例.在那里,隐式传递一个实例(如在Haskell中),但是如果需要,您可以手动覆盖隐式参数并使用特殊语法来指定不同的实例.