在类型类约束中使用`typeError'时避免``undefined''

发布于 2025-02-11 00:01:08 字数 536 浏览 0 评论 0原文

我有一个类型类别的实例:

instance {-# OVERLAPPABLE #-} (TypeError ( 'Text "Some error")) => SomeClass x where
  someMethod = undefined

此实例存在于其他(有效)实例的末尾。当用户写入不符合这些有效实例的类型时,想法是让编译器抛出类型错误。 typeerror在实例约束中实现了这一点,但这也迫使我用undefined填写该方法,感觉就像是黑客攻击。

有没有办法避免这种情况?还是更好?

使用此模式。

I have a type-class instance like this:

instance {-# OVERLAPPABLE #-} (TypeError ( 'Text "Some error")) => SomeClass x where
  someMethod = undefined

This instance exists at the end of other (valid) instances. The idea is to have the compiler throw a type error when the user writes a type that doesn't adhere to these valid instances. TypeError in instance constraint achieves this, but this also forces me to fill in the method with undefined, which feels like a hack.

Is there a way to avoid this? Or do it better?

Here's the real-world code with this pattern.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

毁虫ゝ 2025-02-18 00:01:08

我能实现的最好的方法是。从本质上讲,我定义了typeerr类型的家族代表标准typeerror约束和附加不可能的约束提供所需的见证。 不可能的总是无法作为约束解决,但是无论如何,类型错误还是首先触发。

{-# LANGUAGE DataKinds, UndecidableInstances, TypeFamilies #-}

import GHC.TypeLits (
  ErrorMessage (Text),
  TypeError,
 )

class Impossible where
  impossible :: a

type family TypeErr t where
  TypeErr t = (TypeError t, Impossible)

-- Dummy example
class SomeClass x where
  someMethod :: x -> Maybe x

instance {-# OVERLAPPABLE #-} (TypeErr ( 'Text "Some error")) 
         => SomeClass x where
  someMethod = impossible

main :: IO ()
main = print (someMethod True)
{-
<source>:19:15: error:
    * Some error
    * In the first argument of `print', namely `(someMethod True)'
      In the expression: print (someMethod True)
      In an equation for `main': main = print (someMethod True)
-}

The best I could achieve is this. Essentially, I defined a TypeErr type family standing for both the standard TypeError constraint and an additional Impossible constraint providing the needed witness. Impossible would always fail to resolve as a constraint, but the type error is triggered first anyway.

{-# LANGUAGE DataKinds, UndecidableInstances, TypeFamilies #-}

import GHC.TypeLits (
  ErrorMessage (Text),
  TypeError,
 )

class Impossible where
  impossible :: a

type family TypeErr t where
  TypeErr t = (TypeError t, Impossible)

-- Dummy example
class SomeClass x where
  someMethod :: x -> Maybe x

instance {-# OVERLAPPABLE #-} (TypeErr ( 'Text "Some error")) 
         => SomeClass x where
  someMethod = impossible

main :: IO ()
main = print (someMethod True)
{-
<source>:19:15: error:
    * Some error
    * In the first argument of `print', namely `(someMethod True)'
      In the expression: print (someMethod True)
      In an equation for `main': main = print (someMethod True)
-}
提赋 2025-02-18 00:01:08

我们有不允许 Trevial​​-Constraint软件包中的类。它提供 nope pseudo-method,它是undefined的版本,只能在不可能的上下文中使用(并通过可能“使用” 来见证这一点未包装,您无法使用标准未定义的)。

instance {-# OVERLAPPABLE #-} (Disallowed "fallback for `SomeClass`")
    => SomeClass x where
  someMethod = nope

We have the Disallowed class in the trivial-constraint package. It offers the nope pseudo-method, which is a version of undefined that can only be used in impossible contexts (and witnesses this by being possible to “use” unboxed, which you can't do with standard undefined).

instance {-# OVERLAPPABLE #-} (Disallowed "fallback for `SomeClass`")
    => SomeClass x where
  someMethod = nope
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文