Грешка при анализ на случай

Опитвам се да конвертирам Maybe Int в Int в Haskell по следния начин:

convert :: Maybe Int -> Int
convert mx = case mx of 
               Just x -> x
              Nothing -> error "error message"

Когато го компилирам, Haskell ми казва: parse error on input 'Nothing'.

Имам нужда от това, защото искам да получа индекса на елемент в списък с функцията elem.Index от модула Data.List и след това да използвам този индекс във функцията take. Проблемът ми е, че elemIndex връща Maybe Int, но take се нуждае от Int.


person imc    schedule 27.06.2015    source източник
comment
Надявам се, че разбирате, че „преобразуването“ по този начин не е наистина умна идея: вие по същество подкопавате системата от типове. Направете това само когато сте абсолютно сигурни, че аргументът е Just, но програмата за проверка на типа не може да го докаже. И дори тогава е по-добре изрично да съпоставите case mx of {Just x -> x} точно там, където имате нужда, а не чрез помощна функция. Причината е: ако това съвпадение не е неуспешно, то ще ви даде хубаво ясно съобщение за грешка, показващо къде се е случило. Вашият convert винаги ще ви дава едно и също съобщение за грешка, когато предположението е неуспешно, независимо къде го използвате.   -  person leftaroundabout    schedule 27.06.2015
comment
Звучи сякаш просто се нуждаете от takeWhile (/= item)?   -  person Lee    schedule 27.06.2015


Отговори (2)


Това е проблем с интервали. Клаузите case трябва да бъдат с отстъп на същото ниво.

convert :: Maybe Int -> Int
convert mx = case mx of 
               Just x -> x
               Nothing -> error "error message"

Не забравяйте да използвате само интервали, без раздели.

person leftaroundabout    schedule 27.06.2015
comment
Въпреки това, това, което OP изглежда иска, е fromJust. - person bereal; 27.06.2015
comment
@bereal: mhhhh... Не бих препоръчал fromJust. Вижте коментара ми по-горе към въпроса. (Въпреки това е по-добре от convert.) - person leftaroundabout; 27.06.2015

За да добавя към отговора на @leftaroundabout, мисля, че мога да ви предоставя някои други опции.

Първо, не трябва да правите опасни неща като това: вашата програма ще се провали. Много по-чисто е да го поддържате като Maybe Int и да работите като такъв безопасно. С други думи, това беше проста грешка при анализиране, но правенето на непълни функции като тази може да причини много по-големи проблеми в бъдеще.

Проблемът, който сте срещнали, как мога да го направя?

Можем да направим по-добра функция, като тази:

mapMaybe :: (a -> b) -> Maybe a -> Maybe b
mapMaybe f m = case m of
     Just a  -> f a
     Nothing -> Nothing

Което ще ви позволи да напишете:

λ> (+ 15) `mapMaybe` Just 9
Just 24

Съществува обаче функция, наречена fmap, която „картира“ функция върху определени структури от данни, включително Maybe:

λ> (== 32) `fmap` Just 9
Just False

и ако имате imported Control.Applicative, има хубав синоним на оператора за него:

λ> show <$> Just 9
Just "9"

Ако искате да научите повече за тези структури от данни, наречени Functors, бих препоръчал да прочетете Learn- имате Haskell.

person AJF    schedule 27.06.2015