【问题标题】:NILL value in haskellhaskell 中的 NILL 值
【发布时间】:2010-05-28 23:44:10
【问题描述】:

我从用户那里获得输入 (x),通过 let y = (read x)::Int 将其转换为 Int,然后如果用户什么都不提供(空字符串),我希望函数以特殊方式运行。

-- In this place I would like to handle situation in which user
-- gave empty string as argument
-- this doesnt work :/
yearFilter [] y = True

--This works fine as far as y is integer
yearFilter x y  | x == (objectYear y) = True
                | otherwise = False

感谢您的帮助, 再见

【问题讨论】:

    标签: haskell


    【解决方案1】:

    也许你想要一个Maybe 类型?如果用户输入空字符串,你的函数返回Nothing;否则返回Just n,其中n是用户输入的内容?

    userInt :: String -> Maybe Int
    userInt [] = Nothing
    userInt s  = Just $ read s
    

    (我没有编译这段代码。)

    【讨论】:

      【解决方案2】:

      在这种情况下,Maybe 可能不够用:您需要担心三个条件:

      1. 用户没有输入任何内容
      2. 用户输入有效
      3. 用户输入无法解析

      这个数据类型和函数直接表达了这一点:

      data Input a = NoInput | Input a |  BadInput String
          deriving (Eq, Show)
      
      input :: (Read a) => String -> Input a
      input "" = NoInput
      input s =
          case filter (null.snd) (reads s) of
              ((a,_):_) -> Input a
              otherwise -> BadInput s
      

      请注意,它不是使用不完整的函数read,而是使用reads,这不会在无法转换的输入上出错。 reads 有一个有点尴尬的界面,唉,所以我几乎总是把它包装在一个返回 Maybe a 或类似的函数中。

      使用示例:

      > input "42" :: Input Int
      Input 42
      > input "cat" :: Input Int
      BadInput "cat"
      > input "" :: Input Int
      NoInput
      

      我会像这样编写你的 yearFilter 函数:

      yearFilter :: Maybe Int -> Int -> Bool
      yearFilter Nothing  _ = True
      yearFilter (Just x) y = x == objectYear y
      

      然后我将用户输入处理为:

      inputToMaybe :: Input a -> Maybe a
      inputToMaybe (Input a) = Just a
      inputToMaybe _         = Nothing
      
      do
          a <- input `fmap` getLine
          case a of
              BadInput s -> putStrLn ("Didn't understand " ++ show s)
              otherwise  -> ... yearFilter (inputToMaybe a) ....
      

      注意:我已经稍微清理了yearFilter 中的代码:无需使用守卫从测试中生成布尔值 - 只需返回测试,函数应用程序 (objectYear) 绑定比运算符 (@ 987654333@) 所以去掉括号,用_替换未使用输入的名称。


      好吧,我承认我情不自禁......我又重写了yearFilter,这次我更倾向于写它:

      yearFilter :: Maybe Int -> Int -> Bool
      yearFilter x y = maybe True (== objectYear y) x
      

      了解 Maybemaybe 是了解 Haskell 的第一件事,这让我真正爱上了这门语言。

      【讨论】:

        【解决方案3】:

        除非您明确定义它,否则没有 NULL。你可以像这样检查空字符串。

        readInput :: IO ()
        readInput = do
           ln <- getLine
           if valid ln
              then -- whatever
              else -- whatever
        
        valid x
            | null x                = False
            | not istJust convert x = False
            | otherwise             = True
        where convert :: String -> Maybe Int
              convert = fmap fst $ listToMaybe  . reads $ "f"
        

        【讨论】:

          【解决方案4】:

          'read' 函数无法将空字符串转换为 int,如果您尝试这样做会导致错误。您需要在转换为 int 之前测试输入是否为空字符串。如果您想在用户输入空字符串时使用默认值(例如 0),您可以执行以下操作:

          let y = if null x then 0 else read x
          

          【讨论】:

          • 请不要教人length x == 0。编写此测试的惯用且高效的方式是null x
          • 至于惯用语,点到为止。鉴于“长度”的定义,我无法相信性能会有任何差异。无论如何,我有点惊讶有人觉得有必要投反对票。
          • "length" 会将字符串走到最后以找出长度,如果该字符串是 400203209 个字符,那么您遇到了性能问题。 "null" 将在恒定时间内运行,因为它只需要查看其中是否至少有一个元素。
          • 啊,你的权利。我专注于匹配案例。我感到有点羞愧,因为我最讨厌的一个问题是'IF ((SELECT COUNT (*) ...) > 0) BEGIN ...' vs. 'IF EXISTS (SELECT ...) BEGIN.. .'.同样的问题!
          • 但我会假设长度是预先计算的不可变值。
          猜你喜欢
          • 2015-05-29
          • 1970-01-01
          • 2014-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多