我认为问题的部分原因在于两个基本上不相关的限制正在发挥作用:
- 没有类型同义词实例意味着实例只能是用
data
or newtype
, not type
。这禁止String
, 但不是[Char]
.
- 没有灵活的实例意味着实例只能提及一种不是变量的类型,并且只有该类型可以用作类型构造函数。这禁止
Maybe Int
and f Int
, 但不是Maybe a
.
GHCi 是这样说的Int
, Char
, and String
:
data Char = GHC.Types.C# GHC.Prim.Char#
data Int = GHC.Types.I# GHC.Prim.Int#
type String = [Char]
Int
and Char
都是没有类型变量参数的简单类型;不涉及类型构造函数,因此您可以非常自由地使用它们创建实例。
然而,字符串失败两者都很重要。这是一个类型同义词,这是不允许的,而且它也是一个应用于非变量的类型构造函数,即应用于Char的列表类型构造函数。
为了进行比较,请注意[a]
, Maybe a
, and Either a b
在实例中都有效,但是[Int]
, Maybe [a]
, and Either String a
被禁止;希望您现在能明白原因。
至于你的直接问题,我不知道以这种方式设计语言的最初动机是什么,我也没有资格对“最佳实践”做出权威的陈述,但对于我自己的个人编码,我不这样做毫不犹豫地使用这些编译指示:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
你可以随时去看看。灵活的实例似乎确实得到了相当多的使用,并且来自“受人尊敬的”包(例如,Parsec 的源代码中有一些命中)。