当前位置:  开发笔记 > 编程语言 > 正文

扩展"读取"式行为

如何解决《扩展"读取"式行为》经验,为你挑选了1个好方法。

我正在学习Haskell,我遇到了一个似乎无法解决的问题.基本上,我的用例如下.我正在处理一个字符串; 如果它以一个"字符开头,那么我想把它作为一个字符串返回(带有"剥离); 否则,我想返回它的结果read.换一种说法:

parse "\"foo\"" -> "foo"

parse "3" -> 3

parse "1.5" -> 1.5

到目前为止,我尝试了以下方法.

    多态返回类型

parse :: String -> a
parse ('"':xs) = init xs -- strip closing '"'
parse string = read string

这给出了编译时错误Couldn't match expected type `a' with actual type `[Char]'.不应该a匹配任何类型,包括复杂类型[Char]

    类型类

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class Parse where parse :: String -> a
instance Read a => Parse a where parse = read
instance Parse String where parse = init . tail

这会编译,但会出现以下运行时错误:

Overlapping instances for Parse a0 arising from a use of `parse'
Matching instances:
  instance Read a => Parse a -- Defined at parse.hs:5:14
  instance Parse [Char] -- Defined at parse.hs:7:14
(The choice depends on the instantiation of `a0'
 To pick the first instance above, use -XIncoherentInstances
 when compiling the other instance declarations)

String不是一个实例Read,所以我不太确定它在哪里看到重叠.

顺便说一句,pragma是存在的,因为否则我会遇到编译时错误:

Illegal instance declaration for `Parse [Char]'
  (All instance types must be of the form (T a1 ... an)
   where a1 ... an are *distinct type variables*,
   and each type variable appears at most once in the instance head.
   Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Parse [Char]'

Constraint is no smaller than the instance head
  in the constraint: Read a
(Use -XUndecidableInstances to permit this)
In the instance declaration for `Parse a'

    制作String一个实例Read

我不知道该怎么做,文档对我来说并不是那么清楚.但是,如果我能弄明白的话,听起来这可能是正确的做法.但是有一个问题在我脑海中浮现:如果在一个模块中我创建String了一个实例Read,即使我不导出相关位,它是否会改变整个应用程序的类?如果可以,那么我不确定我喜欢它的含义.


这就是我到目前为止所尝试的内容.我的方法有误吗?它基本上是正确的,我只需要修复几个细节?请告诉我.



1> Daniel Wagne..:

不应该a匹配任何类型,包括复杂类型[Char]

它可以做到.这里的问题是谁可以选择什么a.你写的类型parse :: String -> a是缩写的类型

parse :: forall a. String -> a

你应该读作:"调用者选择一个类型a和一个String s,并parse s产生一个类型的值a".这里的重要部分是调用者,而不是parse选择要替换的类型a.所以,如果你写

parse s = ""

这是一个错误,因为调用者可能会选择其他类型String!您还可以想象一个parse可供选择的类型; 这被称为存在类型,它对调用者如何使用生成的值有一些强烈的限制.

String不是一个实例Read,所以我不太确定它在哪里看到重叠.

你错了:String 一个实例Read.它使用以下两个实例:

instance Read Char -- Defined in ‘GHC.Read’
instance Read a => Read [a] -- Defined in ‘GHC.Read’

(回想一下type String = [Char].)例如,在ghci中:

> read "\"foo\"" :: String
"foo"

也许这个实例足以满足您的目的!

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有