Mam następujący kod:Jak działają wyjątki w Haskell (część druga)?
{-# LANGUAGE DeriveDataTypeable #-}
import Prelude hiding (catch)
import Control.Exception (throwIO, Exception)
import Control.Monad (when)
import Data.Maybe
import Data.Word (Word16)
import Data.Typeable (Typeable)
import System.Environment (getArgs)
data ArgumentParserException = WrongArgumentCount | InvalidPortNumber
deriving (Show, Typeable)
instance Exception ArgumentParserException
data Arguments = Arguments Word16 FilePath String
main = do
args <- return []
when (length args /= 3) (throwIO WrongArgumentCount)
let [portStr, cert, pw] = args
let portInt = readMaybe portStr :: Maybe Integer
when (portInt == Nothing) (throwIO InvalidPortNumber)
let portNum = fromJust portInt
when (portNum < 0 || portNum > 65535) (throwIO InvalidPortNumber)
return $ Arguments (fromInteger portNum) cert pw
-- Newer 'base' has Text.Read.readMaybe but alas, that doesn't come with
-- the latest Haskell platform, so let's not rely on it
readMaybe :: Read a => String -> Maybe a
readMaybe s = case reads s of
[(x, "")] -> Just x
_ -> Nothing
Jego zachowanie różni gdy skompilowany z optymalizacje włączenia i wyłączenia:
crabgrass:~/tmp/signserv/src% ghc -fforce-recomp Main.hs && ./Main
Main: WrongArgumentCount
crabgrass:~/tmp/signserv/src% ghc -O -fforce-recomp Main.hs && ./Main
Main: Main.hs:20:9-34: Irrefutable pattern failed for pattern [portStr, cert, pw]
Dlaczego tak jest? Jestem świadomy, że imprecise exceptions can be chosen from arbitrarily; ale tutaj wybieramy jeden dokładny i jeden nieprecyzyjny wyjątek, więc zastrzeżenie nie powinno mieć zastosowania.
To wygląda jak błąd do mnie. Którą wersję GHC używasz? Widzę to samo zachowanie w GHC 7.6.2. – hammar
@hammar To się dzieje co najmniej 7.6.1 i 7.4.1 tutaj, a osoba, która go wychowała w #haskell, używała wersji 7.0.x. –
@DanielWagner To dziwne, ponieważ na 7.0.2 i 7.0.4 otrzymuję 'WrongArgumentCount'. (Również 6.12.3) –