我有一个名为pitch的客户数据结构,带有2个变量note和octave。我需要将字符串转换为音高,以便编写一个函数,该函数将String作为输入,也许将Pitch作为返回值,因为可能存在一些无效的输入。然后我自定义了show函数,当我在ghci中对其进行测试时,它显示为“ Just A2”(A2是音高值)。这是我的代码:
data Pitch = Pitch { note :: Char, octave :: Int }deriving (Eq)
toPitch :: String -> Maybe Pitch
toPitch str
| strlen == 2 && (note >= 'A' && note <= 'G')
&& (octave >= 1 && octave <= 3) = Just (Pitch note octave)
| otherwise = Nothing
where
strlen = length str
note = head str
octave = digitToInt (str!!1)
toString :: Maybe Pitch -> String
toString (Just pitch) = [note pitch] ++ [(intToDigit (octave pitch))]
instance Show Pitch where
show pitch = toString (Just pitch)
下面是测试结果:
*Main> let pitch = toPitch "A2"
*Main> show pitch
"Just A2"
*Main>
有人可以告诉我如何在show功能中删除它吗?非常感谢!
答案 0 :(得分:3)
我认为Maybe Pitch
值的字符串表示形式并不是您真正想要的。相反,您需要一个Maybe String
值,表示 if 如果您确实有一个Pitch
值,则可以得到一个String
表示形式,但是如果您有{{ 1}},您仍然会得到Nothing
。这仅意味着将Nothing
实例用于Functor
。
这意味着将您的逻辑移到Maybe
的{{1}}实例中:
Show
您通常对Pitch
本身的值不感兴趣;您对自己可能从中提取的instance Show Pitch where
show pitch = note pitch : intToDigit (octave pitch) : ""
值感兴趣。这意味着您通常只想提升Maybe Pitch
来获得Pitch
的值。
show
要清楚一点,如果Maybe String
返回>>> show (Pitch 'A' 2)
"A2"
>>> toPitch "A2"
Just (Pitch 'A' 2)
>>> fmap show (toPitch "A2")
Just "A2" -- not "Just A2"
,那一定是个秀场大战:显然没有合适的默认值可替代。使用toPitch
而不是像
Nothing
仅强制您的其余代码以适当的方式适应失败的可能性,而不仅仅是在Maybe Pitch
无法返回类型toPitch :: String -> Pitch
toPitch str
| strlen == 2 && (note >= 'A' && note <= 'G')
&& (octave >= 1 && octave <= 3) = Pitch note octave
where
strlen = length str
note = head str
octave = digitToInt (str!!1)
的值时因运行时错误而崩溃。
您可能还想使用解析器库来实现toPitch
。例如
Pitch
解析过程更加简单,如果解析器发生故障,您将获得比toPitch
更具描述性的内容。