haskell - 具有相关函数的最小完整定义

标签 haskell ghc

我有以下类型类(省略了不相关的方法):

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’

我的目的是通过提供 initializeinitializePure 来实现 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/

相关文章:

user-interface - Haskell 简单 GUI 程序 : "can' t match X against Maybe X"

list - 递归如何满足基本情况 Haskell

unit-testing - 函数式编程中的测试

haskell - FRP中的“Behavior now”

haskell - GHC REWRITE 编译指示是否必须保留类型?

haskell - 获取 Haskell 程序中的 RTS 线程数?

Haskell 共享库未正确加载

optimization - 在 Haskell 中优化部分计算

haskell - 获取列表列表并生成替换一个元素的所有变体

haskell - 来自实例的约束推断