Haskell 如何导入隐藏子模块或实例的模块?

Haskell 如何导入隐藏子模块或实例的模块?,haskell,import,module,Haskell,Import,Module,使用此代码 import Control.Monad import Control.Applicative import Control.Monad.State class DefVal a where defVal :: a instance (DefVal a) => Alternative (Either a) where empty = Left defVal (Left _) <|> x = x x <|> _ = x

使用此代码

import Control.Monad
import Control.Applicative
import Control.Monad.State

class DefVal a where
  defVal :: a

instance (DefVal a) => Alternative (Either a) where
  empty = Left defVal
  (Left _) <|> x = x
  x        <|> _ = x

instance (DefVal a) => MonadPlus (Either a) where
  mzero = empty
  mplus = (<|>)

newtype ErrString = ErrString { toString :: String }
  deriving Show

instance DefVal ErrString where
  defVal = ErrString "Default Error String"
如果我删除导入
Control.Monad.Trans.Error的
Control.Monad.State
,错误就会消失

如何从那里导入
Control.Monad.State
隐藏
Control.Monad.Trans.Error
或隐藏
可选
MonadPlus
的实例

我使用了GHC-7.10.2,第5.4节规定:

实例声明不能在导入或导出时显式命名 名单。模块范围内的所有实例均始终导出并 任何导入都会从导入的模块中引入所有实例。因此 当且仅当导入链
import
声明导致包含实例声明的模块

因此,标准决定了你不能做你想做的事

原因是,通过允许这样做,可以创建混合不同实例的程序,从而产生不正确的结果

例如,见

有些扩展(例如,
GeneralizedNewtypeDeriving
,请参阅)允许混合实例,即使在导出/导入列表中没有实例

事实上,GHC在这方面已经没有100%遵守标准,并且允许使用格式错误的程序。它不会全局检查实例声明,但只检查在需要它的范围内只有一个实例。看


在您的情况下,您可能应该在
周围使用一些
newtype
,以避免混淆实例:

newtype MyEither e a = MyEither {runMyEither :: Either e a}


instance (DefVal a) => Alternative (MyEither a) where
  empty = MyEither (Left defVal)
  (MyEither (Left _)) <|> x = x
  x                   <|> _ = x

instance (DefVal a) => MonadPlus (MyEither a) where
  mzero = empty
  mplus = (<|>)
newtype MyEither e a=MyEither{runMyEither::e a}
实例(DefVal a)=>备选方案(MyEither a),其中
empty=MyEither(左下)
(MyEither(左)x=x
x ux=x
实例(deffal a)=>MonadPlus(MyEither a)其中
mzero=空
mplus=()
任何人想要一个值
x::或者一个b
充当
x::我的另一个b

只需执行
MyEither x
,然后对结果使用
runMyEither

AFAIK目前绝对无法引用导入/导出列表中的实例。你真倒霉。请参阅:如果始终导入实例,则隐藏模块(如果可能)不会隐藏它们。感谢
newtype
的建议!
newtype MyEither e a = MyEither {runMyEither :: Either e a}


instance (DefVal a) => Alternative (MyEither a) where
  empty = MyEither (Left defVal)
  (MyEither (Left _)) <|> x = x
  x                   <|> _ = x

instance (DefVal a) => MonadPlus (MyEither a) where
  mzero = empty
  mplus = (<|>)