检查一个类型是否是Haskell中的Show实例? [英] Check whether a type is an instance of Show in Haskell?

查看:410
本文介绍了检查一个类型是否是Haskell中的Show实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在Haskell中有一个简单的数据类型来存储值: b

我想让V成为Show的一个实例,而不管其类型如何。如果a是Show的一个实例,那么 show(V a)应该返回 show a 否则应该是错误消息回。或者在伪Haskell中:

pre code> instance Show(V a)where
show(V a)= if a instanceof显示
,然后显示
else有些错误。

这种行为在Haskell中如何实现?

解决方案

正如我在评论中所说的,内存中分配的运行时对象在Haskell程序中没有类型标记。因此,在Java中没有通用的 instanceof 操作。



重要的是要考虑下列。在Haskell中,对于初步近似(即忽略一些初学者不应该过早处理的奇特东西),所有运行时函数调用都是单形的。也就是说,编译器直接或间接地知道可执行程序中每个函数调用的单态(非泛型)类型。即使您的 V 类型的 show 函数具有泛型:

   - 专门用于`V a` 
show :: V a - >字符串 - 通用;有变量`a`

...您实际上无法编写调用该函数的程序运行时没有直接或间接地告诉编译器到底每一次调用中会有什么类型的 a 。例如:

   - 这里直接告诉它:`a:= Int` 
example1 = show V(1 :: Int))

- 这里你不是说哪种类型的`a`,而是这个推迟
- 决定例子2 `要被调用,在调用
- 图中的* something *必须为`a`选择一个单形类型。
example2 :: a - >字符串
example2 x = show(V x)++ example1

由此看来,希望你可以发现你问的问题:

  instance显示(V a)其中
显示V a)=如果显示
的实例然后显示
else有些错误。

基本上,由于 a 参数将在编译时被知道,以便对 show 函数进行实际调用,在运行时没有必要对此类型进行测试 - 您可以在编译时测试它!一旦你掌握了这一点,你就会被引导到Will Sewell的建议:

   - 没有调用`show(V x)`将会编译,除非`x`是`Show`类型。 
实例Show a =>显示(V a)其中...






编辑:一个更有建设性的答案也许可能是这样的:你的 V 类型需要是多个案例的标记联合。这确实需要使用 GADTs 扩展名:

  { - #LANGUAGE GADTs # - } 

- 这个定义需要`GADTs`。它有两个构造函数:
data V a where
- Showable构造函数只能与Show类型一起使用。
Showable :: Show a => a - > V a
- Unshowable构造函数可以用于任何类型。
Unshowable :: a - > V a

实例显示(V a)其中
显示(显示a)=显示
显示(不显示a)=有些错误。

但这不是运行时检查类型是否是 Show 实例 - 您的代码负责在编译时知道要使用 Showable 构造函数。


Suppose I have a simple data type in Haskell for storing a value:

data V a = V a

I want to make V an instance of Show, regardless of a's type. If a is an instance of Show, then show (V a) should return show a otherwise an error message should be returned. Or in Pseudo-Haskell:

instance Show (V a) where
    show (V a) = if a instanceof Show
                   then show a
                   else "Some Error."

How could this behaviour be implemented in Haskell?

解决方案

As I said in a comment, the runtime objects allocated in memory don't have type tags in a Haskell program. There is therefore no universal instanceof operation like in, say, Java.

It's also important to consider the implications of the following. In Haskell, to a first approximation (i.e., ignoring some fancy stuff that beginners shouldn't tackle too soon), all runtime function calls are monomorphic. I.e., the compiler knows, directly or indirectly, the monomorphic (non-generic) type of every function call in an executable program. Even though your V type's show function has a generic type:

-- Specialized to `V a`
show :: V a -> String  -- generic; has variable `a`

...you can't actually write a program that calls the function at runtime without, directly or indirectly, telling the compiler exactly what type a will be in every single call. So for example:

-- Here you tell it directly that `a := Int`
example1 = show (V (1 :: Int)) 

-- Here you're not saying which type `a` is, but this just "puts off" 
-- the decision—for `example2` to be called, *something* in the call
-- graph will have to pick a monomorphic type for `a`.
example2 :: a -> String
example2 x = show (V x) ++ example1

Seen in this light, hopefully you can spot the problem with what you're asking:

instance Show (V a) where
    show (V a) = if a instanceof Show
                   then show a
                   else "Some Error."

Basically, since the type for the a parameter will be known at compilation time for any actual call to your show function, there's no point to testing for this type at runtime—you can test for it at compilation time! Once you grasp this, you're led to Will Sewell's suggestion:

-- No call to `show (V x)` will compile unless `x` is of a `Show` type.
instance Show a => Show (V a) where ...


EDIT: A more constructive answer perhaps might be this: your V type needs to be a tagged union of multiple cases. This does require using the GADTs extension:

{-# LANGUAGE GADTs #-}

-- This definition requires `GADTs`.  It has two constructors:
data V a where
  -- The `Showable` constructor can only be used with `Show` types.
  Showable   :: Show a => a -> V a
  -- The `Unshowable` constructor can be used with any type.
  Unshowable :: a -> V a

instance Show (V a) where
  show (Showable a) = show a
  show (Unshowable a) = "Some Error."

But this isn't a runtime check of whether a type is a Show instance—your code is responsible for knowing at compilation time where the Showable constructor is to be used.

这篇关于检查一个类型是否是Haskell中的Show实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆