在Haskell中为自定义数据类型创建Read type类的实例 [英] Creating instance of Read type class in Haskell for custom data type

查看:124
本文介绍了在Haskell中为自定义数据类型创建Read type类的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义的数据类型 Foo = Foo {a :: Int,b :: Int} ,我试图让Foo成为一个自定义的read实例。我已经有一个函数 bar :: String - > Foo ,我试过这样做:

  instance Read(Foo ab)where 
read s = bar s

但是当我将文件加载到GHCi中进行测试时出现以下错误它: Fraction.hs:11:1:read'不是Read类的(可见)方法



有人可以告诉我什么是问题,我怎么能实际地实例化这种类型? 阅读 typeclass不会声明直接读取;相反,它定义了 readsPrec ,它支持优先级(当读取复杂数据类型的值时这很重要其他类型的元素)。当你使用派生(读取)时,你得到的定义看起来大致像

  instance(Read a)=> Read(Tree a)其中

readsPrec dr = readParen(d> app_prec)
(\r - > [(Leaf m,t)|
(Leaf ,s)-lex r,
(m,t)< - readsPrec(app_prec + 1)s])r
++ readParen(d> up_prec)
( (u:s)< - readsPrec(up_prec + 1)r,
(:^:,t) < - lex s,
(v,w)< - readsPrec(up_prec + 1)t])r
其中app_prec = 10
up_prec = 5

(这显然对于数据类型,但类似的规则适用于其他用户定义的ADT)。 (另外,上面是一个小小的谎言:GHC实际上使用了不同的实现,但是除非你愿意在GHC内部进行挖掘,否则以上就是你应该做的事。)
$根据 readsPrec readList read c $ c>( Read 中的另一种方法,除 Char 以外的每种类型均默认用于读取 [Char] 作为字符串而不是 Char 的列表)。

如果标准派生是不够的,对于类似你的类型,它只是一个 Int s的存储桶,您可以忽略优先级参数。 p>

顺便说一句,读取显示您可能需要考虑其他方式对您的数据进行I / O操作。


I have a custom data type Foo = Foo{ a :: Int, b :: Int} and I'm trying to make Foo a custom instance of read. I already have a function bar :: String -> Foo and I tried doing this:

instance Read (Foo a b) where
    read s = bar s

but I'm getting the following error when I load my file into GHCi to test it: Fraction.hs:11:1: read' is not a (visible) method of class Read'

Could someone tell me what the problem is and how I can actually instantiate this type?

解决方案

The Read typeclass doesn't declare read directly; instead, it defines readsPrec, which supports precedence (this is important when reading a value of a complex data type involving elements of other types). The definition you get when you use deriving (Read) looks roughly like

instance (Read a) => Read (Tree a) where

    readsPrec d r =  readParen (d > app_prec)
                     (\r -> [(Leaf m,t) |
                             ("Leaf",s) <- lex r,
                             (m,t) <- readsPrec (app_prec+1) s]) r
                  ++ readParen (d > up_prec)
                     (\r -> [(u:^:v,w) |
                             (u,s) <- readsPrec (up_prec+1) r,
                             (":^:",t) <- lex s,
                             (v,w) <- readsPrec (up_prec+1) t]) r
      where app_prec = 10
            up_prec = 5

(this obviously for a Tree data type, but similar rules apply for other user-defined ADTs). (Also, the above is a slight lie: GHC actually uses a different implementation, but the above is the kind of thing you should do unless you're willing to dig around inside of GHC.)

read is defined in terms of readsPrec and readList (the other method in Read, which is defaulted for every type except Char where it's used to read [Char] as a string instead of as a list of Char).

If the standard derivation isn't sufficient, for a type like yours that is simply a bucket of Ints you can ignore the precedence parameter.

BTW, Read and Show are rather slow; you may want to consider other ways to do I/O with your data.

这篇关于在Haskell中为自定义数据类型创建Read type类的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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