Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-07 Thread Dimitry Golubovsky
Henning,

On Tue, Sep 7, 2010 at 12:51 PM, Henning Thielemann
 wrote:


> This solution looks very ugly to me. Catching 'error's is debugging, but
> parser failure is kind of exception handling. I guess, the errors you
> want to catch are caused by non-supported fail method, right? Can't you
> use a monad transformer like explicit-exception:Synchronous.Exception or
> transformers:ErrorT around the Binary parser?

Alexey already replied, but after looking at the way Binary processes
parser errors I came to the same conclusion: it is by design that it
falls hard when data cannot be deserialized (btw makes sense in many
cases, but not in mine).

I am beginning to realize that probably (de)serializing lazy
structures is not a good idea at all since such structure may be
consumed in pure code, and such parser errors are hidden inside, and
may "fire" at any moment. Any complications to the binary parser will
bring performance penalty. Or weird solutions like mine are needed.

Thanks.

-- 
Dimitry Golubovsky

Anywhere on the Web
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-07 Thread Ben Millwood
On Tue, Sep 7, 2010 at 2:45 PM, Dimitry Golubovsky  wrote:
> unThrow a = unsafePerformIO $ (E.evaluate a >>= return . Right) `E.catch`
>                                               (\e -> return $ Left e)
>
> -- or perhaps the right argument of catch could be just (return . Left)?
>
> bm2mb :: a -> Maybe a
>
> bm2mb a = case unThrow a of
>   Left (e::SomeException) -> Nothing
>   Right a -> Just a

Philosophically these functions are Nasty because they violate
referential transparency. In particular it's possible for the same
expression to throw different exceptions each time it's run depending
on how it's optimised, what other threads are doing, if the user
presses ctrl-C, etc. etc.
See the spoon package:

http://hackage.haskell.org/package/spoon

which alleviates this a little by only catching some kinds of
exception, and not telling you which it caught. It still violates
monotonicity (I believe), so purists will be upset, but practically it
can be useful for when editing the source code to provide explicit
exceptions (which is ideally what you'd do) is not an option.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-07 Thread Alexey Khudyakov

On 07.09.2010 20:51, Henning Thielemann wrote:

This solution looks very ugly to me. Catching 'error's is debugging, but
parser failure is kind of exception handling. I guess, the errors you
want to catch are caused by non-supported fail method, right? Can't you
use a monad transformer like explicit-exception:Synchronous.Exception or
transformers:ErrorT around the Binary parser?

ErrorT is useless here since it cannot intercept calls to 'error'. Same 
should be the case with ExcepcionalT. There is also performance penalty


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-07 Thread Henning Thielemann
Dimitry Golubovsky schrieb:
> Hi,
> 
> Thanks to everybody who replied.
> 
> I see another solution: are there any hidden problems?
> 
> I found an interesting package, ChasingBottoms which contains a
> function testing a value to be bottom and returning a Boolean (of
> course it cannot be done without unsafePerformIO).
> 
> I borrowed the idea from that package, and wrote two functions:
> 
> unThrow :: (Exception e) => a -> Either e a
> 
> unThrow a = unsafePerformIO $ (E.evaluate a >>= return . Right) `E.catch`
>(\e -> return $ Left e)
> 
> -- or perhaps the right argument of catch could be just (return . Left)?
> 
> bm2mb :: a -> Maybe a
> 
> bm2mb a = case unThrow a of
>Left (e::SomeException) -> Nothing
>Right a -> Just a
> 
> So, if there is a value inside the lazy list which is a bottom (binary
> parse failure of the last received object in this case, catching any
> possible exception) then the value can be converted to Nothing within
> pure code, and then excluded from the result using catMaybes.
> 
> This solution seems to be working for me.

This solution looks very ugly to me. Catching 'error's is debugging, but
parser failure is kind of exception handling. I guess, the errors you
want to catch are caused by non-supported fail method, right? Can't you
use a monad transformer like explicit-exception:Synchronous.Exception or
transformers:ErrorT around the Binary parser?

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-07 Thread Dimitry Golubovsky
Hi,

Thanks to everybody who replied.

I see another solution: are there any hidden problems?

I found an interesting package, ChasingBottoms which contains a
function testing a value to be bottom and returning a Boolean (of
course it cannot be done without unsafePerformIO).

I borrowed the idea from that package, and wrote two functions:

unThrow :: (Exception e) => a -> Either e a

unThrow a = unsafePerformIO $ (E.evaluate a >>= return . Right) `E.catch`
   (\e -> return $ Left e)

-- or perhaps the right argument of catch could be just (return . Left)?

bm2mb :: a -> Maybe a

bm2mb a = case unThrow a of
   Left (e::SomeException) -> Nothing
   Right a -> Just a

So, if there is a value inside the lazy list which is a bottom (binary
parse failure of the last received object in this case, catching any
possible exception) then the value can be converted to Nothing within
pure code, and then excluded from the result using catMaybes.

This solution seems to be working for me.

PS Maybe the way I am using the serialized data needs to be changed by
implementing some kind of an iterator over the binary stream, and then
by taking one object at a time and consuming it right there the
problem might be eliminated entirely...

Thanks again.

-- 
Dimitry Golubovsky

Anywhere on the Web
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-05 Thread Victor Gorokhov
> If however something goes wrong, and prs fails, the whole function
> fails (error is thrown). Since [a] (result of decoding) is a lazy
> list, actual exception may be thrown at any moment the list is being
> processed, and exception handler may not be properly set.

> True -> return (reverse a)
> False -> many' (s:a)
Lazy lists are built in left to right order, but this one is right to left.


> Is there any way to catch/detect failures inside the Get monad?
lookAhead, lookAheadM, etc
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-05 Thread Stephen Tetley
Also any half decent binary format should tell you how long the list
is *before* you parse it, either:

1) How many elements it has - for this you just need a counting
version of the many combinator.

2) The length of bytes that the flattened list takes. In this case the
repeating combinator has to test length remaining before deciding
whether to parse the next element.

Neither should need exceptions.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-05 Thread Henning Thielemann


On Sun, 5 Sep 2010, Dimitry Golubovsky wrote:


Hi,

The following function* is supposed to decode a list of some
serialized objects following each other in a lazy Bytestring:

many :: Get a -> Get [a]

many prs = many' [] where
 many' a = do
   s <- prs
   r <- isEmpty
   case r of
 True -> return (reverse a)
 False -> many' (s:a)

prs is a "parser" to decode a single object.


It is more efficient to call
   fmap (s:) (many prs)
 in the recursion in order to avoid the final 'reverse'. The way you have 
implemented the loop, the complete list must be hold in memory, even if it 
is consumed lazily.


The trick to catch exceptions lazily is to make them explicit, either by 
using
  http://hackage.haskell.org/packages/archive/capped-list/1.2/doc/html/Data-CappedList.html 
or

  
http://hackage.haskell.org/packages/archive/explicit-exception/0.1.5/doc/html/Control-Monad-Exception-Asynchronous.html
 with an enclosed list. The latter solution is the more general one, but 
unfortunately it causes a space leak in GHC.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] How to catch exception within the Get monad (the Binary package)

2010-09-04 Thread Victor Gorokhov
> If however something goes wrong, and prs fails, the whole function
> fails (error is thrown). Since [a] (result of decoding) is a lazy
> list, actual exception may be thrown at any moment the list is being
> processed, and exception handler may not be properly set.

> True -> return (reverse a)
> False -> many' (s:a)

Lazy lists are built in left to right order, but Yours is right to left.


> Is there any way to catch/detect failures inside the Get monad?
lookAhead, lookAheadM, etc
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe