【问题标题】:How to delete the "Just" in customized haskell show function如何删除自定义haskell show功能中的“Just”
【发布时间】:2019-04-01 01:34:50
【问题描述】:

我有一个名为 pitch 的自定义数据结构,其中包含 2 个变量 note 和 octave。我需要将字符串转换为音高,因此我编写了一个函数,该函数将字符串作为输入,将 Maybe Pitch 作为返回值,因为可能存在一些无效输入。然后我自定义了我的显示功能,当我在 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> 

有人可以告诉我如何在显示功能中删除它吗?非常感谢!

【问题讨论】:

  • 如果那里有Nothing呢?
  • 提示:使用case 语句。或者,编写一个模式匹配的新函数。
  • 如果我们确定该变量中存在值,是否有任何方法可以删除 Maybe 包装器?在我的项目中,另一个将 [Pitch] 作为输入而不是 [Maybe Pitch] 的函数。
  • @AJFarmar 你为什么删除你的答案?这正是我看完问题后想写的答案。
  • @DanielWagner 我意识到主要问题是提问者是show@Maybe Pitch,而不是他们写错了show。如果你真的认为它有用,我会恢复它。

标签: haskell


【解决方案1】:

我不认为Maybe Pitch 值的字符串表示是您真正想要的。相反,你想要一个Maybe String 值,表明如果你真的有一个Pitch 值,你可以得到一个String 表示,但是如果你有Nothing,你仍然得到@ 987654326@。这只是意味着将Functor 实例用于Maybe。

这意味着将您的逻辑移动到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。例如

import Text.Parsec

toPitch :: String -> Either ParseError Pitch
toPitch str = parse pitchParser "" str
    where pitchParser = do
            note <- oneOf "ABCDEFG"
            octave <- satisfy (`elem` "123")
            return $ Pitch note (digitToInt octave)

解析过程稍微简单一些,在解析器失败的情况下,您将获得比Nothing 更具描述性的内容。

【讨论】:

    猜你喜欢
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 2019-08-06
    • 2017-05-24
    • 1970-01-01
    相关资源
    最近更新 更多