具有相关函数的最小完整定义
Minimal complete definition with dependent functions
我有以下类型类(省略不相关的方法):
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
编译指示:
{-# MINIMAL initializePure | initialize #-}
但随后我收到了不同的警告:
The MINIMAL pragma does not require:
‘initializePure’
but there is no default implementation.
In the class declaration for ‘Initializable’
我的意图是通过提供 initialize
或 initializePure
来获得 Initializable
,但仅在 initialize
之外使用定义。
如何干净地编译代码?
编译器对此发出警告是非常正确的,因为它不能可以在只能用 IO 初始化的类型上使用 initialisePure
。
确保安全的唯一方法是将两种情况分开;最简单的可能性是 two 类:
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
我有以下类型类(省略不相关的方法):
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
编译指示:
{-# MINIMAL initializePure | initialize #-}
但随后我收到了不同的警告:
The MINIMAL pragma does not require:
‘initializePure’
but there is no default implementation.
In the class declaration for ‘Initializable’
我的意图是通过提供 initialize
或 initializePure
来获得 Initializable
,但仅在 initialize
之外使用定义。
如何干净地编译代码?
编译器对此发出警告是非常正确的,因为它不能可以在只能用 IO 初始化的类型上使用 initialisePure
。
确保安全的唯一方法是将两种情况分开;最简单的可能性是 two 类:
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