我有以下类型类(省略了不相关的方法):
class Initializable a where
initialize :: IO a
initialize = return initializePure
{# convenience method for implementations, not to be called from outside #}
initializePure :: a
data Foo = Foo
instance Initializable Foo where
initializePure = Foo
data Bar = Bar
instance Initializable Bar where
initialize = initializeBar
有些实现需要 IO
来初始化自身,有些则不需要。
这段代码给出了一个警告:
No explicit implementation for
‘initializePure’
In the instance declaration for ‘Initializable Bar’
我尝试添加一个MINIMAL
pragma,如下所示:
{-# MINIMAL initializePure | initialize #-}
但随后我收到了不同的警告:
The MINIMAL pragma does not require:
‘initializePure’
but there is no default implementation.
In the class declaration for ‘Initializable’
我的目的是通过提供 initialize
或 initializePure
来实现 Initialized
,但仅使用 在定义之外初始化
。
如何干净地编译代码?
最佳答案
编译器对此提出警告是非常正确的,因为不可能对只能使用 IO 初始化的类型进行initialisePure
。
确保安全的唯一方法是将两种情况分开;最简单的可能性是有两个类:
class Initialisable a where
initialise :: IO a
class Initialisable a => PureInitialisable a where
initialisePure :: a
data Foo = Foo
instance Initialisable Foo where
initialise = return Foo
instance PureInitialisable Foo where
initialisePure = Foo
data Bar = Bar
initialiseBar :: IO Bar
initialiseBar = undefined
instance Initialisable Bar where
initialise = initialiseBar
您无法为 PureInitialisable
提供默认实现,因为对于某些类型(例如 Bar
),它不存在。但是,如果您打开 DefaultSignatures
,则可以为 Initialisable
指定一个默认值,当类型恰好是 PureInitialisable
时,该默认值就会生效:
{-# LANGUAGE DefaultSignatures #-}
class Initialisable a where
initialise :: IO a
default initialise :: PureInitialisable a => IO a
initialise = return initialisePure
对于像 Foo
这样的类型,这可以让你编写
instance PureInitialisable Foo where initialisePure = Foo
instance Initialisable Foo
稍微短一点。
另一种选择可能是使初始化发生的 monad 可定制:
{-# LANGUAGE TypeFamilies #-}
class Initialisable a where
type InitialisationM a :: *
type InitialisationM a = a
initialise :: InitialisationM a
instance Initialisable Foo where
initialise = Foo
instance Initialisable Bar where
type InitialisationM Bar = IO Bar
initialise = initialiseBar
关于haskell - 具有相关函数的最小完整定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37509719/