Haskell相当于assert(0)

Ore*_*lom 2 haskell assert

我想弄清楚写Haskell等价的最佳做法是什么assert(0).我知道类型安全性要求必须返回一个整数scanList,但是我想知道是否有比我写的更好的方法.有没有办法避免923那些卡在那里的任意数字?

module Main (main) where

import Control.Exception (assert)

l = [
    Left "1",
    Left "1",
    Right 1,
    Right 1,
    Left "9"]

scanList :: [ Either String Int ] -> Int
scanList [    ] = 0
scanList (x:xs) = case x of
    Right i -> i + scanList xs
    Left  s ->
        if read s < 8
        then read s + scanList xs
        else assert False $ 923

main = do
    print $ scanList l
Run Code Online (Sandbox Code Playgroud)

Kar*_*ski 7

来自以下文件assert:

如果第一个参数的计算结果为True,那么结果就是第二个参数.否则会引发AssertionFailed异常,其中包含一个String,其中包含源文件和assert调用的行号.

因此,False您可以在if那里检查您的状况,而不是作为第一个参数给出:

scanList (x:xs) = case x of
    Right i -> i + scanList xs
    Left  s ->
        assert (read s < 8) (read s + scanList xs)
Run Code Online (Sandbox Code Playgroud)


Mar*_*ann 5

更惯用的Haskell设计是保持纯函数的总和.使用时assert,你会抛出异常,这会使函数变为局部.这意味着您无法再信任该函数的类型.它声称具有该类型[Either String Int] -> Int,但在运行时在各种条件下将失败并出现异常.

总函数要么保留在Eithermonad中,要么可以转换为Maybe:

import Text.Read

scanList :: (Num a, Read a, Ord a) => [Either String a] -> Maybe a
scanList [] = Just 0
scanList (x:xs) =
  case x of
    Right i -> fmap (+ i) $ scanList xs
    Left s -> 
      case readMaybe s of
        Just i -> if i < 8 then fmap (+ i) $ scanList xs else Nothing
        Nothing -> Nothing
Run Code Online (Sandbox Code Playgroud)

您可以简化代码,但我选择在结构上保持尽可能接近OP.

与类型一样[Either String a] -> Maybe a,任何调用者都知道,他们必须同时处理JustNothing情况,而不必诉诸阅读有关的功能的代码或文档.

  • @OrenIshShalom有几个原因,异常仍然是Haskell的一部分.其中之一是Haskell是一种古老的语言,并且出于历史或向后兼容的原因,某些语言功能仍然存在.另一个原因是你可以争辩说,在"IO"的情况下,异常仍然是合适的,其中函数已经不纯. (4认同)