Program error prelude read no parse

getting error Prelude.read: no parse I am very new in haskell, i wrote the code for item details and search the detail for each item. code for search but, the problem is, it is working good for single data, if i append another data, then it showing error Prelude.read: no parse when i am […]

Содержание

  1. getting error Prelude.read: no parse
  2. 1 Answer 1
  3. *** Exception: Prelude.read: no parse in Haskell — Parsing, Expressions and Recursion
  4. 1 Answer 1
  5. Haskell Exception: Prelude.read: no parse
  6. 1 Answer 1
  7. Reading a custom data type with error Prelude.read: no parse
  8. 1 Answer 1
  9. Can’t catch «Prelude.read: no parse» exception with Control.Exception.try
  10. 4 Answers 4

getting error Prelude.read: no parse

I am very new in haskell, i wrote the code for item details and search the detail for each item.

code for search

but, the problem is, it is working good for single data, if i append another data, then it showing error Prelude.read: no parse when i am trying to search the item. Help will be appreciated !!

1 Answer 1

Your problem is in the format of your data file. After one use of textfile , the file contains the following:

That’s a good list, and it works. After the second use of textfile , the file contains the following:

That’s not a good list, and it fails. You can see this in ghci :

It’s clear that read expects a single list, not two lists following each other.

If you want to append to a file that contains a single Haskell list, you need to read the file, append to the list, and write the new list in the file as a replacement.

This is a little tricky because of two tings:

  • readFile is lazy, and writeFile to the same file can fail unless one makes sure that the whole file has already been read. In the function above this is solved by asking for the length of the new string before writing the file (the seq function makes sure that the length is computed before the write operation happens).
  • the file may not exist, the catch clause is used above to handle that exceptional case.

Источник

*** Exception: Prelude.read: no parse in Haskell — Parsing, Expressions and Recursion

This portion of code should read in two or more numbers (main io function omitted), then a «+» to give the sum. Rationals are used because later i will do multiplications and such other operations.

The (second) error is with the parse function unable to handle

I have looked on the Data.Ratio page and on the web for this solution but haven’t found it and would appreciate some help. Thanks,

1 Answer 1

The first equation,

since per the type signature, a and b already are Expression s.

Or, in line with the second and third equations, change the type to

and change the first equation to

Two possible ways of fixing the code (there were more problematic parts):

The latter is rather circumspect, since in the end a Double is produced, there’s no real point using Rational s for the stack.

In your code for parse , the third equation leaves out the conversion of a Rational to an Expression via the Number constructor, but is otherwise fine. The second equation, however, contains a different type of problem:

If answer is either an Expression or a Rational , show answer cannot be parsed as a Float , so that will lead to a runtime error, as exemplified by your edit:

The (second) error is with the parse function unable to handle

At the point where the second equation is used, the first element ( answer ) on the stack is Number (3 % 1) , and show (Number (3 % 1)) is «Number (3 % 1)» , which is not a String that read can parse as a Float .

Источник

Haskell Exception: Prelude.read: no parse

I am new to Haskell, kinda 2 days since I study Haskell, and I want to do a project with files. I did it already in c++ and now I want to do it in Haskell too. A little part of project is about a library, where I can register a book and a person. Now I want to put book code into a file.txt but to store it as int, not as String, because I have to search and compare this code , with other codes later, and will be easier to compare. Here is my code, and I receive the following error *** Exception: Prelude.read: no parse. Does anyone know how to solve this please?

1 Answer 1

This fails since you’re attempting to read a String as a String.

read is used to parse a String as an object. To parse a String as a String though, you need to add explicit quotes around the String being parsed. Failing to do so will result in the error that you got. You can test this by adding » s around the input when your program asks for it. It should work.

Do you expect code1 to be an int? If that’s the case, there’s 2 problems (and a couple ways to solve them) :

You need to tell read what type you want it to parse the string as. To do that, use a type annotation. Add :: int after read code .

Since you can’t concatenate an int, change code1 in your last line to (show code1) to convert it back to a String.

The problem with the above way is you’re converting from, then to a String. You could avoid any converting by keeping it as a String by skipping the read altogether:

Источник

Reading a custom data type with error Prelude.read: no parse

I am extremely new to functional programming and I have few custom data types of the following to represent a deck of cards.

Data type for Suit

Data type for Rank

Data type for Card

When I typed read «S3H5» :: Card in my stack ghci console, it shows an exception error of *** Exception: Prelude.read: no parse .

May I ask how to fix this?

I have a string of Card information, for instance, «S3HA» which represents two Cards:

What I am trying to achieve:

When I read the string of «S3HA», I want the output to be an array of

[Card Spade Three, Card Heart Ace]

Please advise! I am relatively new to Haskell functional programming!

And I do not want to modify the source code for the custom data type of Card , Suit and Rank above but utilizing those data types to create an array of [Card] . Could anyone provide ways to parse a string into a [Card] ?

1 Answer 1

As @chi says in the comments to the question, the most straightforward way to achieve your aim is to define the readList method for Card .

For lists, I think you need to redefine the readList method in your Read Card instance. If you do that then the predefined instance Read a => Read [a] will automagically call your own readList , and everything should work.

One possible definition:

However, note also that a default Show and Read instance has some advantages:

  • It is usual — that is, people will know what to expect. With a custom instance, it is necessary to inspect the instance definition in order to use it correctly, while a default instance can be used immediately and effortlessly (except for a lot of typing).
  • It is automatically generated — so it is unlikely there to be errors. It gives you a solid ground to stand on, for free, while a custom definition needs to be thoroughly checked if you want to ship the code in good faith.

Therefore, it may be more reasonable to put the same code into monomorphic functions, like say parseCard , parseCards , renderCard and renderCards , and have the best of both worlds.

Actually, I think custom Read instances are an obscure corner of Haskell. When I was researching for a similar problem a while ago, I could not find any guides on this subject. (Compare with the abundance of guides on, say, cellular automata or free monads.) This is maybe because people mostly live with the default derived instances until they really need to parse a lot of data, which is when advanced parsing libraries, such as parsec , come into play.

Источник

Can’t catch «Prelude.read: no parse» exception with Control.Exception.try

I trying to read some value out of a file and catch every exception that might occur (in the mindset of «Easier to ask for forgiveness than permission»). I am having trouble catching the Prelude.read: no parse exception though. To tell try that it should catch every exception I define tryAny with the explicit type SomeException which to my knowledge is the «super type» of every exception:

With tryAny I seem to be able to catch IO errors:

But the read error will not be caught:

What can I do to catch every exception?

4 Answers 4

return does not evaluate its argument, and thus doesn’t throw any exceptions. The evaluation happens outside of tryAny , when you try to print the result.

Use evaluate (possibly together with force from Control.DeepSeq , depending on your real situation) for that.

After a lot of experimenting with evaluate , force and try , following the suggestions of @Roman Cheplyaka, I’ve come up with this solution, which seems almost blazingly obvious now I see the final result:

This solution splits the process up into a function that will enforce strict evaluation and throw all exceptions and a wrapper that will catch these exceptions. force returns a pure haskell object that itself has to be evaluated first to force deep evaluation of a . From the documentation:

force x fully evaluates x, and then returns it. Note that force x only performs evaluation when the value of force x itself is demanded, so essentially it turns shallow evaluation into deep evaluation.

There are a few subtle points of this implementation that went wrong in my earlier tries:

  • If you use ioA directly as input to force instead of a then you will end up with an object of type IO (IO a) , as evaluate has type b -> IO b . This immediate problem can be solved with some unwrap function of type IO(IO a) -> IO a , but then you will get a problem with the typeclass assumption of NFData a , which now needs to be NFData (IO a) . But for IO a there seems to be no instance declarations available, at least for a::(String,String) .
  • Instead of using two functions you could just use tryAnyStrict = do a . The problem then is that exceptions arising from a will not be caught, for example if ioA is the result of serialized and the file that is to be read from does not exist.
  • You cannot inline try.evaluateIoCompletely in your code without type information, because try needs to know which exception it is supposed to catch. This information is now supplied via the return type of tryAnyStrict which resolves the type e of try :: Exception e => IO a -> IO (Either e a) to the most general exception type SomeException .

Now after I got tryAnyStrict working I still have problems with lazy evaluation, because if a fails — where ioA is the result of read on a string read lazily from a file — (for example the file content does not have the format necessary for read ) then the file is still not completely read and thus still opened. A subsequent write on the file will fail («openFile: resource busy»). So. I might actually rewrite the whole code yet again using readMay or readMaybe as suggested by @kqr and @Roman Cheplyaka and also force a strict read of the file directly.

Источник

OK, that’s useful information. I should be able to figure out what’s going
from that. More tomorrow or the day after…

Hi Ian,

Thanks for looking into this. I am not sure what could be going on. I am
getting the error when building https://github.com/garetxe/haskell-gi.
More precisely, the command that fails is

/home/inaki/.cabal/bin/c2hs —cpp=/usr/bin/gcc —cppopts=-E —cppopts=-D__GLASGOW_HASKELL__=706 —cppopts=-Dlinux_BUILD_OS=1 —cppopts=-Dx86_64_BUILD_ARCH=1 —cppopts=-Dlinux_HOST_OS=1 —cppopts=-Dx86_64_HOST_ARCH=1 —cppopts=-I/usr/include/gobject-introspection-1.0 —cppopts=-I/usr/include/glib-2.0 —cppopts=-I/usr/lib64/glib-2.0/include —include=dist/build/haskell-gi/haskell-gi-tmp —cppopts=-I/usr/lib64/ghc-7.6.3/process-1.1.0.2/include —cppopts=-I/usr/lib64/ghc-7.6.3/directory-1.2.0.1/include —cppopts=-I/usr/lib64/ghc-7.6.3/unix-2.6.0.1/include —cppopts=-I/usr/lib64/ghc-7.6.3/time-1.4.0.1/include —cppopts=-I/usr/lib64/ghc-7.6.3/bytestring-0.10.0.2/include —cppopts=-I/usr/lib64/ghc-7.6.3/base-4.6.0.1/include —cppopts=-I/usr/lib64/ghc-7.6.3/include —output-dir=dist/build/haskell-gi/haskell-gi-tmp —output=GI/Internal/ArgInfo.hs ./GI/Internal/ArgInfo.chs

The file it is trying to compile is
https://github.com/garetxe/haskell-gi/blob/master/GI/Internal/ArgInfo.chs
. (I would be happy to simplify the test case if you think it is necessary,
just let me know.)

As mentioned in the first email, replacing the Read instance in the
C2HS.Gen.Monad fixes compilation for me (and the rest of the build
process works without issues). The previous instance could not work, since
the String it is trying to parse is of the form

Ident «GIBaseInfo» 436424608 (NodeInfo
(«/usr/include/gobject-introspection-1.0/gitypes.h»: line 145)
((«/usr/include/gobject-introspection-1.0/gitypes.h»: line 145),10) (Name
{nameId = 56188}))
Notice that there are no backquotes :) I have no clue why it is trying
to parse this string as an Ident, though, I only did a limited analysis. It
is the kind of thing that the Show instance of Ident in language-c would
produce, though.

And just to double-check: c2hs —version prints
C->Haskell Compiler, version 0.17.2 Crystal Seed, 24 Jan 2009
build platform is «x86_64-linux»
and cabal info language-c tells me that I have version 0.4.5 installed.

I am not sure why I am seeing a problem and you aren’t, but I would be
happy to try anything that you think may clarify things.


Reply to this email directly or view it on GitHub
#87 (comment).

Космодемьян

3 / 3 / 0

Регистрация: 04.11.2018

Сообщений: 123

1

02.06.2020, 18:48. Показов 2649. Ответов 5

Метки haskell (Все метки)


Здравствуйте уважаемые!
Подскажите пожалуйста как исправить ошибку Program error: Prelude.read: no parse
Что я не так делаю?
Программа работает, но не выводит результат закодированной строки

Haskell
1
2
3
4
5
6
7
8
(1022 reductions, 1633 cells)
Main> :main
ENCODE =>
Input the string for encoding: "hello"
Input keys a and b: 1 2
 
This is an encoded string => 
Program error: Prelude.read: no parse

Код:

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
module Main where
import IO
import Data.Char
import Data.Maybe
import Data.List
import qualified Data.Set as Set
 
main = do 
       hSetBuffering stdout NoBuffering
       putStrLn "ENCODE =>"
       putStr "Input the string for encoding: "
       s<- getLine
       putStr "Input keys a and b: "
       a<- getLine
       b<- getLine
       let x= (read a):: Int
       let y= (read b):: Int 
       putStr "This is an encoded string => "    
       print $ encode x y s
 
 
let2int :: Char -> Int
let2int c | isLower c = ord c - ord 'a'
          | otherwise = let2int (toLower c)
 
int2let :: Int -> Char
int2let n = chr (ord 'a' + n)
 
shift :: Char -> Int -> Int -> Char
shift c a b | isLetter c = int2let ((x * a + b) `mod` 26)
            | otherwise = c
            where x = let2int c
 
isCoprime :: Int -> Int -> Bool
isCoprime a b = gcd a b == 1
 
valid_param :: Int -> Bool
valid_param a = isCoprime a 26
 
encode :: Int -> Int -> String -> Maybe String
encode a b xs | valid_param a = Just [shift x a b | x <- xs]
              | otherwise = Nothing

Добавлено через 29 минут

Цитата
Сообщение от Космодемьян
Посмотреть сообщение

Подскажите пожалуйста как исправить ошибку Program error: Prelude.read: no parse

с этой проблемой разобрался, надо было просто ключ с новой строки вводить

Haskell
1
2
3
4
5
6
(1022 reductions, 1633 cells)
Main> :main
ENCODE =>
Input the string for encoding: "hello"
Input keys a and b: 1 
2

а возможно ли сделать так чтобы вводить их в одной строке как я и пытался сделать?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

02.06.2020, 18:48

Ответы с готовыми решениями:

ImageString и ошибка Parse error: parse error, unexpected T_STRING, expecting T_VARIABLE or ‘$’ in
Пишу такую строку

imagestring($image,1,10,10,’mytext’,&amp;black);

Выдаеться такая ошибка
Parse…

Выскакивает ошибка Parse error: parse error, unexpected T_STRING
&lt;?php
/* Здесь мы проверяем существуют ли переменные, которые передала форма обратной связи. Если…

SELECT ошибка Parse error: parse error, unexpected T_VARIABLE in
Помогите найти ошибку
Ошибка: Parse error: parse error, unexpected T_VARIABLE in…

Ошибка «Parse error: parse error, unexpected T_VARIABLE»
Господа! Помогите найти ошибку в коде файла отправки заявки с сайта:
Код ниже. Пишет что ошибка…

5

Curry

4736 / 2992 / 462

Регистрация: 01.06.2013

Сообщений: 6,296

Записей в блоге: 9

02.06.2020, 20:01

2

Лучший ответ Сообщение было отмечено Космодемьян как решение

Решение

Цитата
Сообщение от Космодемьян
Посмотреть сообщение

Input the string for encoding: «hello»

Вводить строку в кавычках стоит только если хочется что бы значение s в самом деле содержало кавычки.

Цитата
Сообщение от Космодемьян
Посмотреть сообщение

сделать так чтобы вводить их в одной строке как я и пытался сделать?

Haskell
1
2
3
4
5
6
       putStr "Input the string for encoding: "
       s<- getLine
       putStr "Input keys a and b: "
       ~[x,y]<- (map read . words) <$> getLine
       putStr "This is an encoded string => "    
       print $ encode x y s

Специально указывать тип x,y не нужно, т.к. потом они подставляются в encode , а её аргументами должны быть Int.
По этому компилятор и так догадается про их тип.



1



3 / 3 / 0

Регистрация: 04.11.2018

Сообщений: 123

03.06.2020, 12:41

 [ТС]

3

ERROR file:.test22.txt:8 — Undefined variable «<$>»

Curry, а почаму такая ошибка вылазит?



0



4736 / 2992 / 462

Регистрация: 01.06.2013

Сообщений: 6,296

Записей в блоге: 9

03.06.2020, 12:56

4

Цитата
Сообщение от Космодемьян
Посмотреть сообщение

а почаму

Приведите программу полностью.



0



Космодемьян

3 / 3 / 0

Регистрация: 04.11.2018

Сообщений: 123

03.06.2020, 13:01

 [ТС]

5

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
module Main where
import IO
import Data.Char
import Data.Maybe
import Data.List
import qualified Data.Set as Set
 
main = do 
       hSetBuffering stdout NoBuffering
       putStrLn "ENCODE =>"
       putStr "Input the string for encoding: "
       s<- getLine
       putStr "Input keys a and b: "
       ~[x,y]<- (map read . words) <$> getLine
       putStr "This is an encoded string => "    
       print $ encode x y s
 
let2int :: Char -> Int
let2int c | isLower c = ord c - ord 'a'
          | otherwise = let2int (toLower c)
 
int2let :: Int -> Char
int2let n = chr (ord 'a' + n)
 
shift :: Char -> Int -> Int -> Char
shift c a b | isLetter c = int2let ((x * a + b) `mod` 26)
            | otherwise = c
            where x = let2int c
 
isCoprime :: Int -> Int -> Bool
isCoprime a b = gcd a b == 1
 
valid_param :: Int -> Bool
valid_param a = isCoprime a 26
 
encode :: Int -> Int -> String -> Maybe String
encode a b xs | valid_param a = Just [shift x a b | x <- xs]
              | otherwise = Nothing

Добавлено через 2 минуты

Haskell
1
2
3
4
5
6
7
8
() :: IO ()
(1378947 reductions, 1797594 cells, 9 garbage collections)
Main> :main
Reading file "C:UsersAdminDesktoptest22.txt":
Parsing........................................................................
Dependency analysis
ERROR file:.test22.txt:8 - Undefined variable "<$>"
Data.Set>



0



4736 / 2992 / 462

Регистрация: 01.06.2013

Сообщений: 6,296

Записей в блоге: 9

03.06.2020, 13:21

6

Космодемьян, вы какую то другую программу запускаете, а не ту что у вас в начале сообщения.
Проверьте где находится программа которую вы приводите и что вы делаете.
Например, открываете окно консоли, переходите в каталог проекта (в какой именно),
потом, допустим, запускаете stack ghci.
И что он в начале выдаёт полностью, с самого начала.



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

03.06.2020, 13:21

Помогаю со студенческими работами здесь

Forum phpbb2.Parse error: parse error, unexpected » in install.php on line 749 Что делать?
Здравствуйте! Я скачал скрипт Forum phpbb2.
Когда я выхожу на главный файл форума через браузер,…

Parse error: parse error, unexpected T_VARIABLE in C:inetlocalhostwww estpearclasses.php on line 11
Подскажите в чем тут дело, такая ошибка
Parse error: parse error, unexpected T_VARIABLE in…

Parse error: parse error, unexpected T_VARIABLE in C:inetlocalhostwww estWorkmain.php on line 33
Хочу попробовать написать свой небольшой менеджер для работы с базами,
написал два скрипта.
при…

Правильное написание строки (Parse error: parse error, unexpected »>» in c:….scr.inc on line 34)
Как правильно записать следующую строку :

&lt;?=&quot;&lt;tr&gt;&lt;td&gt;&lt;div id=&quot;ecategory &lt;a…

Ошибка как исправить PHP Parse error: syntax error, unexpected ‘[‘
Всем привет. Ребята помогите решить проблему.

сайт пишет вот такую ошибку

PHP Parse error:…

PHP — Выскакивает ошибка Parse error: syntax error, unexpected T_STRING in
Всем привет. У меня выскакивает ошибка:
Parse error: syntax error, unexpected…

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

6

В стандарте языка Haskell 98 года присутствует механизм обработки исключений ввода-вывода, который в настоящее время считается устаревшим. Согласно современному подходу все исключения, возникшие как при выполнении чистого кода, так и при осуществлении ввода-вывода, должны обрабатываться единообразно. Этой цели служит единая иерархия типов исключений из модуля Control.Exception, в которую легко можно включать собственные типы исключений. Любой тип исключения должен реализовывать экземпляр класса типов Exception. В модуле Control.Exception объявлено несколько конкретных типов исключений, среди которых IOException (исключения ввода-вывода), ArithException (арифметические ошибки, например, деление на ноль), ErrorCall (вызов функции error), PatternMatchFail (не удалось выбрать подходящий образец в определении функции) и другие.

Простейший способ выполнить действие, которое потенциально может вызвать исключение,– воспользоваться функцией try:

try :: Exception e => IO a -> IO (Either e a)

Функция try пытается выполнить переданное ей действие ввода-вывода и возвращает либо Right <результат действия> либо Left <исключение>, например:

ghci> try (print $ 5 `div` 2) :: IO (Either ArithException ())

2

Right ()

ghci> try (print $ 5 `div` 0) :: IO (Either ArithException ())

Left divide by zero

Обратите внимание, что в данном случае потребовалось явно указать тип выражения, поскольку для вывода типа информации недостаточно. Помимо прочего, указание типа исключения позволяет обрабатывать не все исключения, а только некоторые. В следующем примере исключение функцией try обнаружено не будет:

> try (print $ 5 `div` 0) :: IO (Either IOException ())

*** Exception: divide by zero

Указание типа SomeException позволяет обнаружить любое исключение:

ghci> try (print $ 5 `div` 0) :: IO (Either SomeException ())

Left divide by zero

Попробуем написать программу, которая принимает два числа в виде параметров командной строки, делит первое число на второе и наоборот и выводит результаты. Нашей первой целью будет корректная обработка ошибки деления на ноль.

import Control.Exception

import System.Environment

printQuotients :: Integer -> Integer -> IO ()

printQuotients a b = do

  print $ a `div` b

  print $ b `div` a

params :: [String] -> (Integer, Integer)

params [a,b] = (read a, read b)

main = do

  args <- getArgs

  let (a, b) = params args

  res <- try (printQuotients a b) :: IO (Either ArithException ())

  case res of

    Left e -> putStrLn «Деление на 0!»

    Right () -> putStrLn «OK»

  putStrLn «Конец программы»

Погоняем программу на различных значениях:

$ ./quotients 20 7

2

0

OK

Конец программы

$ ./quotients 0 7

0

Деление на 0!

Конец программы

$ ./quotients 7 0

Деление на 0!

Конец программы

Понятно, что пока эта программа неустойчива к другим видам ошибок. В частности, мы можем «забыть» передать параметры командной строки или передать их не в том количестве:

$ ./quotients

quotients: quotients.hs:10:1-31: Non-exhaustive patterns in function params

$ ./quotients 2 3 4

quotients: quotients.hs:10:1-31: Non-exhaustive patterns in function params

Это исключение генерируется при вызове функции params, если переданный ей список оказывается не двухэлементным. Можно также указать нечисловые параметры:

$ ./quotients a b

quotients: Prelude.read: no parse

Исключение здесь генерируется функцией read, которая не в состоянии преобразовать переданный ей параметр к числовому типу.

Чтобы справиться с любыми возможными исключениями, выделим тело программы в отдельную функцию, оставив в функции main получение параметров командной строки и обработку исключений:

mainAction :: [String] -> IO ()

mainAction args = do

  let (a, b) = params args

  printQuotients a b

main = do

  args <- getArgs

  res <- try (mainAction args) :: IO (Either SomeException ())

  case res of

    Left e -> putStrLn «Ошибка»

    Right () -> putStrLn «OK»

  putStrLn «Конец программы»

Мы были вынуждены заменить тип исключения на SomeException и сделать сообщение об ошибке менее информативным, поскольку теперь неизвестно, исключение какого вида в данном случае произошло.

$ ./quotients a b

Ошибка

Конец программы

$ ./quotients

Ошибка

Конец программы

Понятно, что в общем случае обработка исключения должна зависеть от её типа. Предположим, что у нас имеется несколько обработчиков для исключений разных типов:

handleArith :: ArithException -> IO ()

handleArith _ = putStrLn «Деление на 0!»

handleArgs :: PatternMatchFail -> IO ()

handleArgs _ = putStrLn «Неверное число параметров командной строки!»

handleOthers :: SomeException -> IO ()

handleOthers e = putStrLn $ «Неизвестное исключение: » ++ show e

К сожалению, чтобы увидеть исключение от функции read, нужно воспользоваться наиболее общим типом SomeException.

Вместо того чтобы вручную вызывать функцию обработчика при анализе результата try, можно применить функцию catch, вот её тип:

ghci> :t catch

catch :: Exception e => IO a -> (e -> IO a) -> IO a

ПРИМЕЧАНИЕ. Модуль Prelude экспортирует старую версию функции catch, которая способна обрабатывать только исключения ввода-вывода. Чтобы использовать новый вариант её определения, необходимо использовать скрывающий импорт: import Prelude hiding (catch).

Функция catch принимает в качестве параметров действие и обработчик исключения: если при выполнении действия генерируется исключение, то вызывается его обработчик. Тип обработчика определяет, какие именно исключения будут обработаны. Рассмотрим примеры, в которых функция mainAction вызывается непосредственно в GHCi:

ghci> mainAction [«2″,»0»]

*** Exception: divide by zero

ghci> mainAction [«0″,»2»] `catch` handleArith

0

Деление на 0!

ghci> mainAction [«2″,»0»] `catch` handleArgs

*** Exception: divide by zero

ghci> mainAction [«2″,»0»] `catch` handleOthers

Неизвестное исключение: divide by zero

ghci> mainAction [«a», «b»] `catch` handleArgs

*** Exception: Prelude.read: no parse

ghci> mainAction [«a», «b»] `catch` handleOthers

Неизвестное исключение: Prelude.read: no parse

Если строка, выводимая GHCi, начинается с ***, то соответствующее исключение не было обработано. Обратите внимание на обычный для функции catch инфиксный способ вызова. Заметьте также, что обработчик handleOthers способен обработать любое исключение.

Вернёмся к основной программе. Нам хочется, чтобы возникшее исключение было обработано наиболее подходящим образом: если произошло деление на ноль, то следует выполнить handleArith, при неверном числе параметров командной строки – handleArgs, в остальных случаях – handleOthers. В этом нам поможет функция catches, посмотрим на её тип:

> :t catches

catches :: IO a -> [Handler a] -> IO a

Функция catches принимает в качестве параметров действие и список обработчиков (функций, которые упакованы конструктором данных Handler) и возвращает результат действия. Если в процессе выполнения происходит исключение, то вызывается первый из подходящих по типу исключения обработчиков (поэтому, в частности, обработчик handleOthers должен быть последним). Перепишем функцию main так, чтобы корректно обрабатывались все возможные исключительные ситуации:

main = do

  args <- getArgs

  mainAction args `catches`

                   [Handler handleArith,

                    Handler handleArgs,

                    Handler handleOthers]

  putStrLn «Конец программы»

Посмотрим, как она теперь работает:

$ ./quotients 20 10

2

0

Конец программы

$ ./quotients

Неверное число параметров командной строки!

Конец программы

$ ./quotients 2 0

Деление на 0!

Конец программы

$ ./quotients a b

Неизвестное исключение: Prelude.read: no parse

Конец программы

В этом разделе мы разобрались с работой функций try, catch и catches, позволяющих обработать исключение, в том числе и возникшее в чистом коде. Заметьте ещё раз, что вся обработка выполнялась в рамках действий ввода-вывода. Посмотрим теперь, как работать с исключениями, которые возникают при выполнении операций ввода-вывода.

я новичок в haskell, я выполняю свое задание, это касается банковской системы, я получаю эту ошибку, когда хочу зарегистрировать новую учетную запись Ошибка программы: Prelude.read: нет синтаксического анализа

код ниже:

createAcc :: IO()
createAcc = do
        new <- readFile "db.txt"                          --Database named db--
        let new1 = length (func new)
        putStrLn " Enter your Name : "      --write your name--
        name <- getLine
        putStrLn " Enter Balance :"         --enter minimum balance to deposit--
        bal <- getLine
        let bal1 = read bal :: Int                         
        store <- readFile "db.txt"                    --entries comes in  database--
        let store1 = func store
        let store2 = store1 ++ [(new1+1,name,bal1)]
        writeFile "db.txt" (show store2)
func :: String -> [(Int,String,Int)] 
func x = read x:: [(Int,String,Int)]

1 ответы

Там, наверное, ничего нет db.txt, поэтому чтение не выполняется. Попробуйте инициализировать файл текстом «[]».

Кроме того, в вашем подходе есть много вещей, которых следует остерегаться… ленивый ввод-вывод не годится для написания надежных программ. Вы можете узнать больше в Интернете, но, по сути, чтение может не произойти, пока вы не получите фактический доступ к содержимому файла, например, с помощью func. Как минимум, вы должны использовать deepseq чтобы заставить чтение происходить там, где вы ожидаете.

Создан 05 сен.

Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками

haskell

or задайте свой вопрос.

I was working with using Haskell on the command line recently and it occurred to
me that it might be interesting to demo it and walk through some error handling
scenarios at the same time.

Like Perl, Python and Ruby you can invoke ghc on the command line to run
programs on the fly. Yes, Haskell makes for a good scripting language.

Let’s say we have a column of numbers that we want to add up. You may have
gotten these from a report you generated on your code repository or from
anywhere. You can use ghc to sum up the numbers.

% cat /tmp/nums
9
3
4


% cat /tmp/nums | ghc -c 'interact ((++ "n") . show . sum . map read . lines)'
16

The interact function will read from stdin and send output to stdout
without any work on our part. It just requires that your code can accept a
String and produces a String. We then break up the input into separate
lines, use read to convert the String to Nums, add them up and turn the
result back into a String.

We could just as well have put the code into a file as another way of using it
in our command line pipeline.

% cat sum.hs

main = interact ((++ "n") . show . sum . map read . lines)


% cat /tmp/nums | runhaskell sum.hs
16

Error Handling Style 1

Let’s say that our column of numbers didn’t always contain good data. Once in a
while we’d get a bad dataset that didn’t have a number in it. How would our code
react?

% cat /tmp/nums-error
9
3
not a num
4


% cat /tmp/nums-error | ghc -e 'interact ((++ "n") . show . sum . map read . lines)'
*** Exception: Prelude.read: no parse

Though we don’t have any exception handling code in place, the read function
chooses to throw an ErrorCall Exception which will halt processing and print
out a somewhat related, but kind of generic message. This might be enough for us
if all we wanted was a quick hack to sum some numbers. But if this was to grow
into some long term code that might occasionally get bad data, the error
handling would need to be a bit better because right now we’re left wondering
what failed to parse.

Error Handling Style 2

Well now we’ll just move our code into a file since it will be much easier to
work with it that way. We’ll introduce another function, catch, which will be
used to catch the ErrorCall Exception raised by read so that we can
interject a better error message. You’ll notice that we’re hiding the catch
function found in the Prelude. That’s because it only catches IOErrors as
you can see from the type signature, catch :: IO a -> (IOError -> IO a) -> IO a. What we want is the catch that’s in Control.Exception since it will
catch what we want.

-- sum.hs
import Prelude hiding ( catch )
import Control.Exception
import System.IO

main = catch (interact ((++ "n") . show . sum . map read . lines))
	(e -> hPutStrLn stderr ("couldn't sum lines: " ++ show e))


% cat /tmp/nums-error | runhaskell sum.hs
couldn't sum lines: Prelude.read: no parse

Well this worked a little better than before. We caught the exception ourselves
and added a message. But we could still use a bit more information. If we had a
large dataset and this code bombed on something in the middle of it, we’d be
left wondering what failed to parse and how could we debug this. If we want
better error reporting, we’re going to have to add more code.

Error Handling Style 3

Style 2 was a big improvement over style 1 in that we we’re explicitly catching
the exception that was thrown. The big problem though, was that we didn’t have
enough context information … we didn’t have the line from the dataset that was
bad.

main = do
  m <- hGetContents stdin
  nums <- mapM readM . lines $ m
  print (sum nums)
  `catch` (e -> hPutStrLn stderr ("couldn't sum lines: " ++ show e))

readM :: (Monad m, Read a) => String -> m a
readM s | [x] <- parse = return x
        | otherwise    = fail $ "Failed to parse "" ++ s ++ "" as a number."
  where
    parse = [x | (x,_) <- reads s]

While the code may look considerably different than before, it’s still doing the
same simple steps. The main difference is that instead of using Prelude.read,
we’ve written a custom function readM that will run in any Monad. If it is
unable to convert a String into the Num type that we expect, it will get a
pattern match failure on [x] <- parse and will instead match up against the
otherwise guard. From there we signal a fail with our more descriptive
error.

The main function has changed a bit to handle our new monadic read function.
Instead of interact we’re manually reading from stdin. But notice that our
exception handler is the same as before. It didn’t need to change. So how well
does this version work?

% cat /tmp/nums-error | runhaskell sum.hs
couldn't sum lines: user error (Failed to parse "not a num" as a number.)

Well there we go. Now we know what to search for in our dataset if we encounter
a problem.

Summary

One can use Haskell as a scripting language similar to others. Furthermore,
language features which are hard wired into other languages such as exception
handling, are actually implemented as libraries in Haskell. This ability to
extend the language via libraries both makes it very powerful for experts, but a
bit overwhelming for newbies who are confused by the myriad ways to do things.
The examples presented hopefully give some simple starting steps that people can
build on to learn more.

Code

-- sum.hs

{-# LANGUAGE PatternGuards #-}
import Prelude hiding ( catch )
import Control.Exception
import Control.Monad ( liftM )
import System.IO

main = style1

style1 = interact ((++ "n") . show . sum . map read . lines)

style2 = catch (interact ((++ "n") . show . sum . map read . lines))
         (e -> hPutStrLn stderr ("couldn't sum lines: " ++ show e))

style3 = do
  m <- hGetContents stdin
  nums <- mapM readM . lines $ m
  print (sum nums)
  `catch` (e -> hPutStrLn stderr ("couldn't sum lines: " ++ show e))


readM :: (Monad m, Read a) => String -> m a
readM s | [x] <- parse = return x
        | otherwise    = fail $ "Failed to parse "" ++ s ++ "" as a number."
  where
    parse = [x | (x,_) <- reads s]

Понравилась статья? Поделить с друзьями:
  • Program error invalid path or file name
  • Program error 7003 prolog
  • Profuis282u dll ошибка windows 7 как исправить
  • Profile server db version is unsupported due to being too high как исправить
  • Professional treatment in each sentence find one spelling error