在Haskell中,如何在返回类型上获得“不可预测的”重载?

时间:2018-12-18 16:51:10

标签: haskell polymorphism overloading typeclass

我有一些类型实例。我们将它们称为A,B和C。它们都是类型类X的实例。现在,我想创建一个单独的函数create,该函数在给定某些输入的情况下创建A,B或C的实例(比如说一个字符串)。类型系统无法知道什么输入将提供什么类型。那是Haskell不喜欢的东西,我想我知道答案,但我想确定。我得到的当前错误是:

• Couldn't match expected type ‘c’ with actual type ‘GCCCommand’
  ‘c’ is a rigid type variable bound by
    the type signature for:
      compiler :: forall c. CompilerCommand c => String -> c
    at src/System/Command/Typed/CC.hs:29:1-44
• In the expression: gcc path
  In an equation for ‘compiler’:
      compiler path
        | exe == "g++" || exe == "gcc" || exe == "cc" || exe == "cpp"
        = gcc path
        where
            exe = takeFileName path
• Relevant bindings include
    compiler :: String -> c
      (bound at src/System/Command/Typed/CC.hs:31:1)

我怀疑这是否意味着在这种特殊情况下不可能在返回类型上重载,因为编译器无法预先知道数据在内存中的外观?您将如何实现此功能?我正在考虑创建类似以下的内容:

data SuperX = SuperA A | SuperB B | SuperC C

create :: String -> SuperX
-- create can now be implemented

instance X SuperX where
  -- a lot of boilerplate code ...

但是,样板代码建议可以做得更好。这真的是最好的方法吗?

1 个答案:

答案 0 :(得分:2)

这取决于您需要如何处理。

如果以后的处理对它们进行ABC的处理{em> ,则不关心它们,只是它实现了{ {1}} ...

X

然后您可以使用延续传递:

restOfProgram :: X a => a -> ThingIWantToCompute

或存在数据包装器:

parseABC :: (X a => a -> r) -> String -> Maybe r
parseABC f "A" = Just (f A)
parseABC f ('B':xs) = Just (f (B xs))
parseABC f ('C':xs) = Just (f (C (read xs)))
parseABC _ _ = Nothing

如果以后的处理对于data SomeX where SomeX :: X t => t -> SomeX parseABC :: String -> Maybe SomeX parseABC "A" = Just (SomeX A) parseABC ('B':xs) = Just (SomeX (B xs)) parseABC ('C':xs) = Just (SomeX (C (read xs))) parseABC _ _ = Nothing restOfProgram' :: SomeX -> ThingIWantToCompute restOfProgram' (SomeX t) = restOfProgram t AB具有不同的路径,则您可能希望返回类似C的求和类型。