读取Haskell中的实例
我创建了一个类似于读取Haskell中的实例,haskell,Haskell,我创建了一个类似于的类型,可能 数据定义a=为|未定义 我做了Showinstance instance Show a => Show (Defined a) where show (Is a) = show a show Undefined = "?" 因此,我尝试实现实例Read instance Read a => Read (Defined a) where readsPrec _ s = case (take 1 s) of
的类型,可能
数据定义a=为|未定义
我做了Show
instance
instance Show a => Show (Defined a) where
show (Is a) = show a
show Undefined = "?"
因此,我尝试实现实例Read
instance Read a => Read (Defined a) where
readsPrec _ s = case (take 1 s) of
"?" -> [(Undefined,tail s)]
otherwise -> map (\(a,b) -> (Is a,b)) $ readsPrec 0 s
这是工作,但我不明白为什么。为什么这里没有无限循环:
otherwise -> map (\(a,b) -> (Is a,b)) $ readsPrec 0 s
readsPrec 0 s
尝试读取输入中的相同字符串,不是吗?所以它必须转到否则
块,并形成一个无限循环。但代码确实有效
readsPrec 0 s
尝试读取输入中的相同字符串,不是吗
是的,它是,但它不是相同的readsPrec
!让我添加几个类型注释:
{-# LANGUAGE ScopedTypeVariables #-}
instance Read a => Read (Defined a) where
readsPrec _ = readsDefined
readsDefined :: forall a . Read a => String -> ReadS (Defined a)
readsDefined s = case (take 1 s) of
"?" -> [(Undefined,tail s)]
otherwise -> map (\(a,b) -> (Is a,b)) $ readsContent s
where readsContent :: String -> ReadS a
readsContent = readsPrec 0
请注意,在这里我不能用
readsDefined
替换readsContent
,它们是两个不同的函数,具有不兼容的类型签名。这与代码中的情况相同,只是readsDefined
和readsContent
都是readsPrec
方法的(不同)实例化,也就是说,它们共享相同的名称,但仍有不同的实现。注意,Haskell中避免使用此类Show
和Read
实例:Show
应生成有效的Haskell代码,因此,“?”
不会产生任何结果。如果您想做的只是漂亮的打印,例如ghci,然后你应该继续使用Maybe
容器,只是。对于我来说,使用标准的Maybe
容器可能不是一个好主意,因为我用不同的行为创建了Eq
定义的类型的Eq
实例?我打赌这是一个更糟糕的主意(但是如果你正确地隐藏了未定义的构造函数,它可能还可以)。无论如何,你不应该让显示(Is a)
只打印a
值,而不提及它被包装在定义的(Nothing==Nothing)
中在Eq
for的实现中是真的可能这不是我想要的定义的类型,因此,我必须创建自己的类型,或者为重载Eq
,这可能更糟。但是,您不应该希望Undefined==Undefined
为false!至少不会,除非Undefined
确实是一种在应用程序中永远不会出现的异常值。(是的,我知道类似地,对于浮点数,IEEE754指定NaN==NaN
为false,但这确实是一个可怕的黑客攻击,它自己也造成了很多问题。)