Haskell 将[Char]与读取的实例匹配
我对用户定义的数据结构和Haskell 将[Char]与读取的实例匹配,haskell,instance,Haskell,Instance,我对用户定义的数据结构和Read 首先是我的数据结构 data Nat = Null | Succ Nat 我的read函数定义如下 readNatNat :: String -> Nat readNatNat xs |first == '(' = readNatNat (tail xs) |first == ' ' = readNatNat (tail xs) |firstFour == "Succ" = (Succ
Read
首先是我的数据结构
data Nat = Null | Succ Nat
我的read函数定义如下
readNatNat :: String -> Nat
readNatNat xs |first == '(' = readNatNat (tail xs)
|first == ' ' = readNatNat (tail xs)
|firstFour == "Succ" = (Succ (readNatNat(drop 4 xs)))
|firstFour == "Null" = Null
|b `elem` [0..] = toNatInt(b)
where b = (read(xs)::Int)
first = head xs
firstFour = take 4 xs
toNatInt :: Int -> Nat
toNatInt x | x==0 = Null
| x<0 = error "Unter Null gibts kein Int 2 Nat"
| otherwise = Succ(toNatInt(x-1))
instance Show Nat where
show (Succ a) = showsRealSucc(Succ a)
show Null = show "Null"
showsRealSucc :: Nat -> String
showsRealSucc Null = "Null"
showsRealSucc (Succ a) = (if a/= Null then ("Succ ("++showsRealSucc(a)++")")
else "Succ Null")
对其他实例(如Enum
、Eq
、Show
等)进行编程非常简单。
我知道Read
需要一个Int,但我不知道为什么;)
我认为Read
与show
相反,它获取一个String
并将其解析到我的数据结构中
我这样定义了Show
readNatNat :: String -> Nat
readNatNat xs |first == '(' = readNatNat (tail xs)
|first == ' ' = readNatNat (tail xs)
|firstFour == "Succ" = (Succ (readNatNat(drop 4 xs)))
|firstFour == "Null" = Null
|b `elem` [0..] = toNatInt(b)
where b = (read(xs)::Int)
first = head xs
firstFour = take 4 xs
toNatInt :: Int -> Nat
toNatInt x | x==0 = Null
| x<0 = error "Unter Null gibts kein Int 2 Nat"
| otherwise = Succ(toNatInt(x-1))
instance Show Nat where
show (Succ a) = showsRealSucc(Succ a)
show Null = show "Null"
showsRealSucc :: Nat -> String
showsRealSucc Null = "Null"
showsRealSucc (Succ a) = (if a/= Null then ("Succ ("++showsRealSucc(a)++")")
else "Succ Null")
为了让您了解Nat:
它是自然数的表示形式,因此当我键入readnat“3”
时,输出为
“(成功(成功(成功无效))”
提前谢谢 readsPrec
采用优先参数
所以
readsPrec
采用一个附加的Int
参数来指示周围上下文中的优先级,因此,例如,如果您正在读取Just Null
,则周围的优先级为10,函数应用程序
在您的情况下,我认为您可以使用实用程序函数readParen::Bool->ReadS a->ReadS a
来处理:
instance Read Nat where
readsPrec prec = readParen prec natReads where
natReads xs = [(readNatNat xs,"")]
readsPrec
应该是一个小型解析器
[]
,而不是导致错误字符串
部分中返回输入的剩余部分2.返回剩余部分: 这种变通方法不适用于
readsPrec
的工作方式。列表[(a,String)]
应该由可能的解析和剩余字符串组成,因此readsPrec 5“Null,Null,suc Null]”
应该是[(Null,Null,suc Null]”]
。正如我在这里试图提示的那样,在解析值列表等时可以使用未使用的输入的剩余部分
重要提示:如果您不这样做,您很可能从
读取“[Null,succnull]”
中得到错误的结果
很少会有多个可能的解析,但例如,如果您决定将Nat
值显示为“0+1+1”
,则需要为该输入生成列表[(Null,+1”),(suc Null,+1”),(suc(suc Null),”)]
这意味着您应该在进出的过程中检查括号的数量,以便在剩余字符串中返回适当的金额:readsPrec 3“((Succ(Succ-Null);”)”
应该是[(Succ(Succ-Null),”))]
1。不要引起错误,返回[]
如果输入不是有效的Nat,则需要返回[]
。我发现了三个问题:
where b = (read(xs)::Int) -- could crash
first = head xs -- could crash
| x<0 = error "Unter Null gibts kein Int 2 Nat" -- crashes
这样您就可以
fmapPairs-Succ(readParen-False)
找到“Succ”
时的剩余部分。如果你需要更多的提示来完成这项工作,请告诉我(我认为你已经证明了自己的能力,这是一个很好的练习,因为你已经了解了更多关于readsPrec
).请提供Read
实例。如果查看Read
类,您将看到它定义函数readsPrec::Int->String->[(a,String)]
。您的函数显然没有这种类型。第一个参数是一个优先上下文,用于更开明的解析。返回类型必须是解析和剩余字符串的列表。要将函数转换为有效格式,您可以编写readsPrec\ux=[(readnat x,”)
@user2407038。信不信由你,这就是我在回答时想说的全部内容,但我想我有点得意忘形了!在不编写正确的readsPrec
的情况下修复类型错误的问题是,有时在读取列表等时会遇到问题。末尾的字符串应该是未使用的输入,readsPrec
不应该像readnat
在无效输入时那样崩溃-它应该只返回[]
。
where b = (read(xs)::Int) -- could crash
first = head xs -- could crash
| x<0 = error "Unter Null gibts kein Int 2 Nat" -- crashes
fmapPairs :: (a -> b) -> [(a,String)] -> [(a,String)]
fmapPairs f pairs = [(f a,xs) | (a,xs) <- pairs]