Get rid of Maybes in complex types

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Baa
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Get rid of Maybes in complex types

Baa
Hello Dear List!

Consider, I retrieve from external source some data. Internally it's
represented as some complex type with `Maybe` fields, even more, some
of fields are record types and have `Maybe` fields too. They are
Maybe's because some information in this data can be missing (user
error or it not very valuable and can be skipped):

  data A = A {
    a1 :: Maybe B
    ... }
  data B = B {
    b1 :: Maybe C
    ... }

I retrieve it from network, files, i.e. external world, then I validate
it, report errors of some missing fields, fix another one (which can be
fixed, for example, replace Nothing with `Just default_value` or even I
can fix `Just wrong` to `Just right`, etc, etc). After all of this, I
know that I have "clean" data, so all my complex types now have `Just
right_value` fields. But I need to process them as optional, with
possible Nothing case! To avoid it I must create copies of `A`, `B`,
etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure,
it's not a case.

After processing and filtering, I create, for example, some resulting
objects:

  data Result {
    a :: A -- not Maybe!
    ... }

And even more: `a::A` in `Result` (I know it, after filtering) will not
contain Nothings, only `Just right_values`s.

But each function which consumes `A` must do something with possible
Nothing values even after filtering and fixing of `A`s.

I have, for example, function:

  createResults :: [A] -> [Result]
  createResults alst =
    ...
    case of (a1 theA) ->
      Just right_value -> ...
      Nothing ->
        logError
        undefined -- can not happen

Fun here is: that it happens (I found bug in my filtering
code with this `undefined`). But now I thought about it: what is the
idiomatic way to solve such situation? When you need to have:

  - COMPLEX type WITH Maybes
  - the same type WITHOUT Maybes

Alternative is to keep this Maybes to the very end of processing, what I
don't like. Or to have types copies, which is more terrible, sure.

PS. I threw IOs away to show only the crux of the problem.

---
Cheers,
  Paul
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Imants Cekusins
Identity 


may work: 

 data A m = A {
    a1 :: m B
 }
  data B m = B {
    b1 :: m C
    ... }

m: Maybe or Identity

- any good?



On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
Hello Dear List!

Consider, I retrieve from external source some data. Internally it's
represented as some complex type with `Maybe` fields, even more, some
of fields are record types and have `Maybe` fields too. They are
Maybe's because some information in this data can be missing (user
error or it not very valuable and can be skipped):

  data A = A {
    a1 :: Maybe B
    ... }
  data B = B {
    b1 :: Maybe C
    ... }

I retrieve it from network, files, i.e. external world, then I validate
it, report errors of some missing fields, fix another one (which can be
fixed, for example, replace Nothing with `Just default_value` or even I
can fix `Just wrong` to `Just right`, etc, etc). After all of this, I
know that I have "clean" data, so all my complex types now have `Just
right_value` fields. But I need to process them as optional, with
possible Nothing case! To avoid it I must create copies of `A`, `B`,
etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure,
it's not a case.

After processing and filtering, I create, for example, some resulting
objects:

  data Result {
    a :: A -- not Maybe!
    ... }

And even more: `a::A` in `Result` (I know it, after filtering) will not
contain Nothings, only `Just right_values`s.

But each function which consumes `A` must do something with possible
Nothing values even after filtering and fixing of `A`s.

I have, for example, function:

  createResults :: [A] -> [Result]
  createResults alst =
    ...
    case of (a1 theA) ->
      Just right_value -> ...
      Nothing ->
        logError
        undefined -- can not happen

Fun here is: that it happens (I found bug in my filtering
code with this `undefined`). But now I thought about it: what is the
idiomatic way to solve such situation? When you need to have:

  - COMPLEX type WITH Maybes
  - the same type WITHOUT Maybes

Alternative is to keep this Maybes to the very end of processing, what I
don't like. Or to have types copies, which is more terrible, sure.

PS. I threw IOs away to show only the crux of the problem.

---
Cheers,
  Paul
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Baa
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Baa
But will it work if I switch from one monad to another? Actually, I
have something like piping/conduit, and if I switch items in pipe from
`A Maybe` to `A Idenitity` - will it work? Whether it will be compiled?

Although I certainly can "map" items from one type to another...
Idea looks interesting sure :)


> Identity
>
> http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Identity.html
>
> may work:
>
>  data A m = A {
>     a1 :: m B
>  }
>   data B m = B {
>     b1 :: m C
>     ... }
>
> m: Maybe or Identity
>
> - any good?
>
>
>
> On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
>
> > Hello Dear List!
> >
> > Consider, I retrieve from external source some data. Internally it's
> > represented as some complex type with `Maybe` fields, even more,
> > some of fields are record types and have `Maybe` fields too. They
> > are Maybe's because some information in this data can be missing
> > (user error or it not very valuable and can be skipped):
> >
> >   data A = A {
> >     a1 :: Maybe B
> >     ... }
> >   data B = B {
> >     b1 :: Maybe C
> >     ... }
> >
> > I retrieve it from network, files, i.e. external world, then I
> > validate it, report errors of some missing fields, fix another one
> > (which can be fixed, for example, replace Nothing with `Just
> > default_value` or even I can fix `Just wrong` to `Just right`, etc,
> > etc). After all of this, I know that I have "clean" data, so all my
> > complex types now have `Just right_value` fields. But I need to
> > process them as optional, with possible Nothing case! To avoid it I
> > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`,
> > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case.
> >
> > After processing and filtering, I create, for example, some
> > resulting objects:
> >
> >   data Result {
> >     a :: A -- not Maybe!
> >     ... }
> >
> > And even more: `a::A` in `Result` (I know it, after filtering) will
> > not contain Nothings, only `Just right_values`s.
> >
> > But each function which consumes `A` must do something with possible
> > Nothing values even after filtering and fixing of `A`s.
> >
> > I have, for example, function:
> >
> >   createResults :: [A] -> [Result]
> >   createResults alst =
> >     ...
> >     case of (a1 theA) ->
> >       Just right_value -> ...
> >       Nothing ->
> >         logError
> >         undefined -- can not happen
> >
> > Fun here is: that it happens (I found bug in my filtering
> > code with this `undefined`). But now I thought about it: what is the
> > idiomatic way to solve such situation? When you need to have:
> >
> >   - COMPLEX type WITH Maybes
> >   - the same type WITHOUT Maybes
> >
> > Alternative is to keep this Maybes to the very end of processing,
> > what I don't like. Or to have types copies, which is more terrible,
> > sure.
> >
> > PS. I threw IOs away to show only the crux of the problem.
> >
> > ---
> > Cheers,
> >   Paul
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >  

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Frerich Raabe
In reply to this post by Baa
On 2017-07-06 10:12, Baa wrote:

> Consider, I retrieve from external source some data. Internally it's
> represented as some complex type with `Maybe` fields, even more, some
> of fields are record types and have `Maybe` fields too. They are
> Maybe's because some information in this data can be missing (user
> error or it not very valuable and can be skipped):
>
>   data A = A {
>     a1 :: Maybe B
>     ... }
>   data B = B {
>     b1 :: Maybe C
>     ... }
>
> I retrieve it from network, files, i.e. external world, then I validate
> it, report errors of some missing fields, fix another one (which can be
> fixed, for example, replace Nothing with `Just default_value` or even I
> can fix `Just wrong` to `Just right`, etc, etc). After all of this, I
> know that I have "clean" data, so all my complex types now have `Just
> right_value` fields. But I need to process them as optional, with
> possible Nothing case! To avoid it I must create copies of `A`, `B`,
> etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure,
> it's not a case.

I understand that your data structures as sketched above are only needed for
a short time, when reading/validating/fixing the input data - the rest of the
program would either report an error (for unrecoverable problems) or process
the validated data?

In that case, maybe you can avoid using Maybe in your data types for things
which definitely must be present completely but rather returning a 'Maybe'
value from your function which retrieves the data, i.e.:

   retrieveData :: ByteString -> Maybe A

Within 'retrieveData' you could then use different weakly-typed data
structures which maybe only represent subsets of the data as you
parse/validate/fix it. Not sure if/how that would work out, but maybe you
could share some more concrete code (e.g. the actual logic for retrieving the
data and the data types)?

--
Frerich Raabe - [hidden email]
www.froglogic.com - Multi-Platform GUI Testing
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Imants Cekusins
In reply to this post by Baa
how about a function (or a Monad Transformer) that checks values in one place: 

check::A Maybe -> Maybe (A Identity)

after values were checked, the after-checked functions will deal with A Identity 

the end result would be 
   Maybe out



On 6 July 2017 at 13:01, Baa <[hidden email]> wrote:
But will it work if I switch from one monad to another? Actually, I
have something like piping/conduit, and if I switch items in pipe from
`A Maybe` to `A Idenitity` - will it work? Whether it will be compiled?

Although I certainly can "map" items from one type to another...
Idea looks interesting sure :)


> Identity
>
> http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Identity.html
>
> may work:
>
>  data A m = A {
>     a1 :: m B
>  }
>   data B m = B {
>     b1 :: m C
>     ... }
>
> m: Maybe or Identity
>
> - any good?
>
>
>
> On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
>
> > Hello Dear List!
> >
> > Consider, I retrieve from external source some data. Internally it's
> > represented as some complex type with `Maybe` fields, even more,
> > some of fields are record types and have `Maybe` fields too. They
> > are Maybe's because some information in this data can be missing
> > (user error or it not very valuable and can be skipped):
> >
> >   data A = A {
> >     a1 :: Maybe B
> >     ... }
> >   data B = B {
> >     b1 :: Maybe C
> >     ... }
> >
> > I retrieve it from network, files, i.e. external world, then I
> > validate it, report errors of some missing fields, fix another one
> > (which can be fixed, for example, replace Nothing with `Just
> > default_value` or even I can fix `Just wrong` to `Just right`, etc,
> > etc). After all of this, I know that I have "clean" data, so all my
> > complex types now have `Just right_value` fields. But I need to
> > process them as optional, with possible Nothing case! To avoid it I
> > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`,
> > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case.
> >
> > After processing and filtering, I create, for example, some
> > resulting objects:
> >
> >   data Result {
> >     a :: A -- not Maybe!
> >     ... }
> >
> > And even more: `a::A` in `Result` (I know it, after filtering) will
> > not contain Nothings, only `Just right_values`s.
> >
> > But each function which consumes `A` must do something with possible
> > Nothing values even after filtering and fixing of `A`s.
> >
> > I have, for example, function:
> >
> >   createResults :: [A] -> [Result]
> >   createResults alst =
> >     ...
> >     case of (a1 theA) ->
> >       Just right_value -> ...
> >       Nothing ->
> >         logError
> >         undefined -- can not happen
> >
> > Fun here is: that it happens (I found bug in my filtering
> > code with this `undefined`). But now I thought about it: what is the
> > idiomatic way to solve such situation? When you need to have:
> >
> >   - COMPLEX type WITH Maybes
> >   - the same type WITHOUT Maybes
> >
> > Alternative is to keep this Maybes to the very end of processing,
> > what I don't like. Or to have types copies, which is more terrible,
> > sure.
> >
> > PS. I threw IOs away to show only the crux of the problem.
> >
> > ---
> > Cheers,
> >   Paul
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Baa
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Baa
Imants, I'm not sure that I understood signatures.

Why
  check::A Maybe -> Maybe (A Identity)

but not
  check::A Maybe -> A Identity

?

To filter (Nothing items must be throw out)? No more reasons for it?


> how about a function (or a Monad Transformer) that checks values in
> one place:
>
> check::A Maybe -> Maybe (A Identity)
>
> after values were checked, the after-checked functions will deal with
> A Identity
>
> the end result would be
>    Maybe out
>
>
>
> On 6 July 2017 at 13:01, Baa <[hidden email]> wrote:
>
> > But will it work if I switch from one monad to another? Actually, I
> > have something like piping/conduit, and if I switch items in pipe
> > from `A Maybe` to `A Idenitity` - will it work? Whether it will be
> > compiled?
> >
> > Although I certainly can "map" items from one type to another...
> > Idea looks interesting sure :)
> >
> >  
> > > Identity
> > >
> > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ 
> > Control-Monad-Identity.html  
> > >
> > > may work:
> > >
> > >  data A m = A {
> > >     a1 :: m B
> > >  }
> > >   data B m = B {
> > >     b1 :: m C
> > >     ... }
> > >
> > > m: Maybe or Identity
> > >
> > > - any good?
> > >
> > >
> > >
> > > On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
> > >  
> > > > Hello Dear List!
> > > >
> > > > Consider, I retrieve from external source some data. Internally
> > > > it's represented as some complex type with `Maybe` fields, even
> > > > more, some of fields are record types and have `Maybe` fields
> > > > too. They are Maybe's because some information in this data can
> > > > be missing (user error or it not very valuable and can be
> > > > skipped):
> > > >
> > > >   data A = A {
> > > >     a1 :: Maybe B
> > > >     ... }
> > > >   data B = B {
> > > >     b1 :: Maybe C
> > > >     ... }
> > > >
> > > > I retrieve it from network, files, i.e. external world, then I
> > > > validate it, report errors of some missing fields, fix another
> > > > one (which can be fixed, for example, replace Nothing with `Just
> > > > default_value` or even I can fix `Just wrong` to `Just right`,
> > > > etc, etc). After all of this, I know that I have "clean" data,
> > > > so all my complex types now have `Just right_value` fields. But
> > > > I need to process them as optional, with possible Nothing case!
> > > > To avoid it I must create copies of `A`, `B`, etc, where `a1`,
> > > > `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not
> > > > a case.
> > > >
> > > > After processing and filtering, I create, for example, some
> > > > resulting objects:
> > > >
> > > >   data Result {
> > > >     a :: A -- not Maybe!
> > > >     ... }
> > > >
> > > > And even more: `a::A` in `Result` (I know it, after filtering)
> > > > will not contain Nothings, only `Just right_values`s.
> > > >
> > > > But each function which consumes `A` must do something with
> > > > possible Nothing values even after filtering and fixing of `A`s.
> > > >
> > > > I have, for example, function:
> > > >
> > > >   createResults :: [A] -> [Result]
> > > >   createResults alst =
> > > >     ...
> > > >     case of (a1 theA) ->
> > > >       Just right_value -> ...
> > > >       Nothing ->
> > > >         logError
> > > >         undefined -- can not happen
> > > >
> > > > Fun here is: that it happens (I found bug in my filtering
> > > > code with this `undefined`). But now I thought about it: what
> > > > is the idiomatic way to solve such situation? When you need to
> > > > have:
> > > >
> > > >   - COMPLEX type WITH Maybes
> > > >   - the same type WITHOUT Maybes
> > > >
> > > > Alternative is to keep this Maybes to the very end of
> > > > processing, what I don't like. Or to have types copies, which
> > > > is more terrible, sure.
> > > >
> > > > PS. I threw IOs away to show only the crux of the problem.
> > > >
> > > > ---
> > > > Cheers,
> > > >   Paul
> > > > _______________________________________________
> > > > Beginners mailing list
> > > > [hidden email]
> > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > >  
> >
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >  

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Imants Cekusins
Why.. 

what would 
    check::A Maybe -> A Identity

do if some A field were Nothing?  fill in a default value?

On 6 July 2017 at 14:13, Baa <[hidden email]> wrote:
Imants, I'm not sure that I understood signatures.

Why
  check::A Maybe -> Maybe (A Identity)

but not
  check::A Maybe -> A Identity

?

To filter (Nothing items must be throw out)? No more reasons for it?


> how about a function (or a Monad Transformer) that checks values in
> one place:
>
> check::A Maybe -> Maybe (A Identity)
>
> after values were checked, the after-checked functions will deal with
> A Identity
>
> the end result would be
>    Maybe out
>
>
>
> On 6 July 2017 at 13:01, Baa <[hidden email]> wrote:
>
> > But will it work if I switch from one monad to another? Actually, I
> > have something like piping/conduit, and if I switch items in pipe
> > from `A Maybe` to `A Idenitity` - will it work? Whether it will be
> > compiled?
> >
> > Although I certainly can "map" items from one type to another...
> > Idea looks interesting sure :)
> >
> >
> > > Identity
> > >
> > > http://hackage.haskell.org/package/mtl-2.2.1/docs/
> > Control-Monad-Identity.html
> > >
> > > may work:
> > >
> > >  data A m = A {
> > >     a1 :: m B
> > >  }
> > >   data B m = B {
> > >     b1 :: m C
> > >     ... }
> > >
> > > m: Maybe or Identity
> > >
> > > - any good?
> > >
> > >
> > >
> > > On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
> > >
> > > > Hello Dear List!
> > > >
> > > > Consider, I retrieve from external source some data. Internally
> > > > it's represented as some complex type with `Maybe` fields, even
> > > > more, some of fields are record types and have `Maybe` fields
> > > > too. They are Maybe's because some information in this data can
> > > > be missing (user error or it not very valuable and can be
> > > > skipped):
> > > >
> > > >   data A = A {
> > > >     a1 :: Maybe B
> > > >     ... }
> > > >   data B = B {
> > > >     b1 :: Maybe C
> > > >     ... }
> > > >
> > > > I retrieve it from network, files, i.e. external world, then I
> > > > validate it, report errors of some missing fields, fix another
> > > > one (which can be fixed, for example, replace Nothing with `Just
> > > > default_value` or even I can fix `Just wrong` to `Just right`,
> > > > etc, etc). After all of this, I know that I have "clean" data,
> > > > so all my complex types now have `Just right_value` fields. But
> > > > I need to process them as optional, with possible Nothing case!
> > > > To avoid it I must create copies of `A`, `B`, etc, where `a1`,
> > > > `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not
> > > > a case.
> > > >
> > > > After processing and filtering, I create, for example, some
> > > > resulting objects:
> > > >
> > > >   data Result {
> > > >     a :: A -- not Maybe!
> > > >     ... }
> > > >
> > > > And even more: `a::A` in `Result` (I know it, after filtering)
> > > > will not contain Nothings, only `Just right_values`s.
> > > >
> > > > But each function which consumes `A` must do something with
> > > > possible Nothing values even after filtering and fixing of `A`s.
> > > >
> > > > I have, for example, function:
> > > >
> > > >   createResults :: [A] -> [Result]
> > > >   createResults alst =
> > > >     ...
> > > >     case of (a1 theA) ->
> > > >       Just right_value -> ...
> > > >       Nothing ->
> > > >         logError
> > > >         undefined -- can not happen
> > > >
> > > > Fun here is: that it happens (I found bug in my filtering
> > > > code with this `undefined`). But now I thought about it: what
> > > > is the idiomatic way to solve such situation? When you need to
> > > > have:
> > > >
> > > >   - COMPLEX type WITH Maybes
> > > >   - the same type WITHOUT Maybes
> > > >
> > > > Alternative is to keep this Maybes to the very end of
> > > > processing, what I don't like. Or to have types copies, which
> > > > is more terrible, sure.
> > > >
> > > > PS. I threw IOs away to show only the crux of the problem.
> > > >
> > > > ---
> > > > Cheers,
> > > >   Paul
> > > > _______________________________________________
> > > > Beginners mailing list
> > > > [hidden email]
> > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > >
> >
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Baa
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Baa
In reply to this post by Frerich Raabe
Unfortunately it's a lot of code and it's not open source :(
As I understood you, function `retrieveData` should make a final
decision: to be or not to be?

It's idea too, but possible will lead to more refactoring.


Thu, 06 Jul 2017 12:02:12 +0200
Frerich Raabe <[hidden email]> wrote:

> On 2017-07-06 10:12, Baa wrote:
> > Consider, I retrieve from external source some data. Internally it's
> > represented as some complex type with `Maybe` fields, even more,
> > some of fields are record types and have `Maybe` fields too. They
> > are Maybe's because some information in this data can be missing
> > (user error or it not very valuable and can be skipped):
> >
> >   data A = A {
> >     a1 :: Maybe B
> >     ... }
> >   data B = B {
> >     b1 :: Maybe C
> >     ... }
> >
> > I retrieve it from network, files, i.e. external world, then I
> > validate it, report errors of some missing fields, fix another one
> > (which can be fixed, for example, replace Nothing with `Just
> > default_value` or even I can fix `Just wrong` to `Just right`, etc,
> > etc). After all of this, I know that I have "clean" data, so all my
> > complex types now have `Just right_value` fields. But I need to
> > process them as optional, with possible Nothing case! To avoid it I
> > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`,
> > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case.  
>
> I understand that your data structures as sketched above are only
> needed for a short time, when reading/validating/fixing the input
> data - the rest of the program would either report an error (for
> unrecoverable problems) or process the validated data?
>
> In that case, maybe you can avoid using Maybe in your data types for
> things which definitely must be present completely but rather
> returning a 'Maybe' value from your function which retrieves the
> data, i.e.:
>
>    retrieveData :: ByteString -> Maybe A
>
> Within 'retrieveData' you could then use different weakly-typed data
> structures which maybe only represent subsets of the data as you
> parse/validate/fix it. Not sure if/how that would work out, but maybe
> you could share some more concrete code (e.g. the actual logic for
> retrieving the data and the data types)?
>

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Baa
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Baa
In reply to this post by Imants Cekusins
Hmm, yes. `Nothing` becomes `Identity default_value`. Respectively `A
Maybe` becomes `A Identity`. I'm not sure will it work but it looks
alluringly ;)

> > Why..  
>
> what would
>     check::A Maybe -> A Identity
>
> do if some A field were Nothing?  fill in a default value?
>
> On 6 July 2017 at 14:13, Baa <[hidden email]> wrote:
>
> > Imants, I'm not sure that I understood signatures.
> >
> > Why
> >   check::A Maybe -> Maybe (A Identity)
> >
> > but not
> >   check::A Maybe -> A Identity
> >
> > ?
> >
> > To filter (Nothing items must be throw out)? No more reasons for it?
> >
> >  
> > > how about a function (or a Monad Transformer) that checks values
> > > in one place:
> > >
> > > check::A Maybe -> Maybe (A Identity)
> > >
> > > after values were checked, the after-checked functions will deal
> > > with A Identity
> > >
> > > the end result would be
> > >    Maybe out
> > >
> > >
> > >
> > > On 6 July 2017 at 13:01, Baa <[hidden email]> wrote:
> > >  
> > > > But will it work if I switch from one monad to another?
> > > > Actually, I have something like piping/conduit, and if I switch
> > > > items in pipe from `A Maybe` to `A Idenitity` - will it work?
> > > > Whether it will be compiled?
> > > >
> > > > Although I certainly can "map" items from one type to another...
> > > > Idea looks interesting sure :)
> > > >
> > > >  
> > > > > Identity
> > > > >
> > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ 
> > > > Control-Monad-Identity.html  
> > > > >
> > > > > may work:
> > > > >
> > > > >  data A m = A {
> > > > >     a1 :: m B
> > > > >  }
> > > > >   data B m = B {
> > > > >     b1 :: m C
> > > > >     ... }
> > > > >
> > > > > m: Maybe or Identity
> > > > >
> > > > > - any good?
> > > > >
> > > > >
> > > > >
> > > > > On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
> > > > >  
> > > > > > Hello Dear List!
> > > > > >
> > > > > > Consider, I retrieve from external source some data.
> > > > > > Internally it's represented as some complex type with
> > > > > > `Maybe` fields, even more, some of fields are record types
> > > > > > and have `Maybe` fields too. They are Maybe's because some
> > > > > > information in this data can be missing (user error or it
> > > > > > not very valuable and can be skipped):
> > > > > >
> > > > > >   data A = A {
> > > > > >     a1 :: Maybe B
> > > > > >     ... }
> > > > > >   data B = B {
> > > > > >     b1 :: Maybe C
> > > > > >     ... }
> > > > > >
> > > > > > I retrieve it from network, files, i.e. external world,
> > > > > > then I validate it, report errors of some missing fields,
> > > > > > fix another one (which can be fixed, for example, replace
> > > > > > Nothing with `Just default_value` or even I can fix `Just
> > > > > > wrong` to `Just right`, etc, etc). After all of this, I
> > > > > > know that I have "clean" data, so all my complex types now
> > > > > > have `Just right_value` fields. But I need to process them
> > > > > > as optional, with possible Nothing case! To avoid it I must
> > > > > > create copies of `A`, `B`, etc, where `a1`, `b1` will be
> > > > > > `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case.
> > > > > >
> > > > > > After processing and filtering, I create, for example, some
> > > > > > resulting objects:
> > > > > >
> > > > > >   data Result {
> > > > > >     a :: A -- not Maybe!
> > > > > >     ... }
> > > > > >
> > > > > > And even more: `a::A` in `Result` (I know it, after
> > > > > > filtering) will not contain Nothings, only `Just
> > > > > > right_values`s.
> > > > > >
> > > > > > But each function which consumes `A` must do something with
> > > > > > possible Nothing values even after filtering and fixing of
> > > > > > `A`s.
> > > > > >
> > > > > > I have, for example, function:
> > > > > >
> > > > > >   createResults :: [A] -> [Result]
> > > > > >   createResults alst =
> > > > > >     ...
> > > > > >     case of (a1 theA) ->
> > > > > >       Just right_value -> ...
> > > > > >       Nothing ->
> > > > > >         logError
> > > > > >         undefined -- can not happen
> > > > > >
> > > > > > Fun here is: that it happens (I found bug in my filtering
> > > > > > code with this `undefined`). But now I thought about it:
> > > > > > what is the idiomatic way to solve such situation? When you
> > > > > > need to have:
> > > > > >
> > > > > >   - COMPLEX type WITH Maybes
> > > > > >   - the same type WITHOUT Maybes
> > > > > >
> > > > > > Alternative is to keep this Maybes to the very end of
> > > > > > processing, what I don't like. Or to have types copies,
> > > > > > which is more terrible, sure.
> > > > > >
> > > > > > PS. I threw IOs away to show only the crux of the problem.
> > > > > >
> > > > > > ---
> > > > > > Cheers,
> > > > > >   Paul
> > > > > > _______________________________________________
> > > > > > Beginners mailing list
> > > > > > [hidden email]
> > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > > > >  
> > > >
> > > > _______________________________________________
> > > > Beginners mailing list
> > > > [hidden email]
> > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > >  
> >
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >  

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Imants Cekusins
is it possible to replace Nothing with defaults when A, B are init'ed ?

On 6 July 2017 at 14:33, Baa <[hidden email]> wrote:
Hmm, yes. `Nothing` becomes `Identity default_value`. Respectively `A
Maybe` becomes `A Identity`. I'm not sure will it work but it looks
alluringly ;)

> > Why..
>
> what would
>     check::A Maybe -> A Identity
>
> do if some A field were Nothing?  fill in a default value?
>
> On 6 July 2017 at 14:13, Baa <[hidden email]> wrote:
>
> > Imants, I'm not sure that I understood signatures.
> >
> > Why
> >   check::A Maybe -> Maybe (A Identity)
> >
> > but not
> >   check::A Maybe -> A Identity
> >
> > ?
> >
> > To filter (Nothing items must be throw out)? No more reasons for it?
> >
> >
> > > how about a function (or a Monad Transformer) that checks values
> > > in one place:
> > >
> > > check::A Maybe -> Maybe (A Identity)
> > >
> > > after values were checked, the after-checked functions will deal
> > > with A Identity
> > >
> > > the end result would be
> > >    Maybe out
> > >
> > >
> > >
> > > On 6 July 2017 at 13:01, Baa <[hidden email]> wrote:
> > >
> > > > But will it work if I switch from one monad to another?
> > > > Actually, I have something like piping/conduit, and if I switch
> > > > items in pipe from `A Maybe` to `A Idenitity` - will it work?
> > > > Whether it will be compiled?
> > > >
> > > > Although I certainly can "map" items from one type to another...
> > > > Idea looks interesting sure :)
> > > >
> > > >
> > > > > Identity
> > > > >
> > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/
> > > > Control-Monad-Identity.html
> > > > >
> > > > > may work:
> > > > >
> > > > >  data A m = A {
> > > > >     a1 :: m B
> > > > >  }
> > > > >   data B m = B {
> > > > >     b1 :: m C
> > > > >     ... }
> > > > >
> > > > > m: Maybe or Identity
> > > > >
> > > > > - any good?
> > > > >
> > > > >
> > > > >
> > > > > On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
> > > > >
> > > > > > Hello Dear List!
> > > > > >
> > > > > > Consider, I retrieve from external source some data.
> > > > > > Internally it's represented as some complex type with
> > > > > > `Maybe` fields, even more, some of fields are record types
> > > > > > and have `Maybe` fields too. They are Maybe's because some
> > > > > > information in this data can be missing (user error or it
> > > > > > not very valuable and can be skipped):
> > > > > >
> > > > > >   data A = A {
> > > > > >     a1 :: Maybe B
> > > > > >     ... }
> > > > > >   data B = B {
> > > > > >     b1 :: Maybe C
> > > > > >     ... }
> > > > > >
> > > > > > I retrieve it from network, files, i.e. external world,
> > > > > > then I validate it, report errors of some missing fields,
> > > > > > fix another one (which can be fixed, for example, replace
> > > > > > Nothing with `Just default_value` or even I can fix `Just
> > > > > > wrong` to `Just right`, etc, etc). After all of this, I
> > > > > > know that I have "clean" data, so all my complex types now
> > > > > > have `Just right_value` fields. But I need to process them
> > > > > > as optional, with possible Nothing case! To avoid it I must
> > > > > > create copies of `A`, `B`, etc, where `a1`, `b1` will be
> > > > > > `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case.
> > > > > >
> > > > > > After processing and filtering, I create, for example, some
> > > > > > resulting objects:
> > > > > >
> > > > > >   data Result {
> > > > > >     a :: A -- not Maybe!
> > > > > >     ... }
> > > > > >
> > > > > > And even more: `a::A` in `Result` (I know it, after
> > > > > > filtering) will not contain Nothings, only `Just
> > > > > > right_values`s.
> > > > > >
> > > > > > But each function which consumes `A` must do something with
> > > > > > possible Nothing values even after filtering and fixing of
> > > > > > `A`s.
> > > > > >
> > > > > > I have, for example, function:
> > > > > >
> > > > > >   createResults :: [A] -> [Result]
> > > > > >   createResults alst =
> > > > > >     ...
> > > > > >     case of (a1 theA) ->
> > > > > >       Just right_value -> ...
> > > > > >       Nothing ->
> > > > > >         logError
> > > > > >         undefined -- can not happen
> > > > > >
> > > > > > Fun here is: that it happens (I found bug in my filtering
> > > > > > code with this `undefined`). But now I thought about it:
> > > > > > what is the idiomatic way to solve such situation? When you
> > > > > > need to have:
> > > > > >
> > > > > >   - COMPLEX type WITH Maybes
> > > > > >   - the same type WITHOUT Maybes
> > > > > >
> > > > > > Alternative is to keep this Maybes to the very end of
> > > > > > processing, what I don't like. Or to have types copies,
> > > > > > which is more terrible, sure.
> > > > > >
> > > > > > PS. I threw IOs away to show only the crux of the problem.
> > > > > >
> > > > > > ---
> > > > > > Cheers,
> > > > > >   Paul
> > > > > > _______________________________________________
> > > > > > Beginners mailing list
> > > > > > [hidden email]
> > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > > > >
> > > >
> > > > _______________________________________________
> > > > Beginners mailing list
> > > > [hidden email]
> > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > >
> >
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Baa
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Baa
Unfortunately, no.

> is it possible to replace Nothing with defaults when A, B are
> init'ed ?
>
> On 6 July 2017 at 14:33, Baa <[hidden email]> wrote:
>
> > Hmm, yes. `Nothing` becomes `Identity default_value`. Respectively
> > `A Maybe` becomes `A Identity`. I'm not sure will it work but it
> > looks alluringly ;)
> >  
> > > > Why..  
> > >
> > > what would
> > >     check::A Maybe -> A Identity
> > >
> > > do if some A field were Nothing?  fill in a default value?
> > >
> > > On 6 July 2017 at 14:13, Baa <[hidden email]> wrote:
> > >  
> > > > Imants, I'm not sure that I understood signatures.
> > > >
> > > > Why
> > > >   check::A Maybe -> Maybe (A Identity)
> > > >
> > > > but not
> > > >   check::A Maybe -> A Identity
> > > >
> > > > ?
> > > >
> > > > To filter (Nothing items must be throw out)? No more reasons
> > > > for it?
> > > >
> > > >  
> > > > > how about a function (or a Monad Transformer) that checks
> > > > > values in one place:
> > > > >
> > > > > check::A Maybe -> Maybe (A Identity)
> > > > >
> > > > > after values were checked, the after-checked functions will
> > > > > deal with A Identity
> > > > >
> > > > > the end result would be
> > > > >    Maybe out
> > > > >
> > > > >
> > > > >
> > > > > On 6 July 2017 at 13:01, Baa <[hidden email]> wrote:
> > > > >  
> > > > > > But will it work if I switch from one monad to another?
> > > > > > Actually, I have something like piping/conduit, and if I
> > > > > > switch items in pipe from `A Maybe` to `A Idenitity` - will
> > > > > > it work? Whether it will be compiled?
> > > > > >
> > > > > > Although I certainly can "map" items from one type to
> > > > > > another... Idea looks interesting sure :)
> > > > > >
> > > > > >  
> > > > > > > Identity
> > > > > > >
> > > > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ 
> > > > > > Control-Monad-Identity.html  
> > > > > > >
> > > > > > > may work:
> > > > > > >
> > > > > > >  data A m = A {
> > > > > > >     a1 :: m B
> > > > > > >  }
> > > > > > >   data B m = B {
> > > > > > >     b1 :: m C
> > > > > > >     ... }
> > > > > > >
> > > > > > > m: Maybe or Identity
> > > > > > >
> > > > > > > - any good?
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On 6 July 2017 at 11:12, Baa <[hidden email]> wrote:
> > > > > > >  
> > > > > > > > Hello Dear List!
> > > > > > > >
> > > > > > > > Consider, I retrieve from external source some data.
> > > > > > > > Internally it's represented as some complex type with
> > > > > > > > `Maybe` fields, even more, some of fields are record
> > > > > > > > types and have `Maybe` fields too. They are Maybe's
> > > > > > > > because some information in this data can be missing
> > > > > > > > (user error or it not very valuable and can be skipped):
> > > > > > > >
> > > > > > > >   data A = A {
> > > > > > > >     a1 :: Maybe B
> > > > > > > >     ... }
> > > > > > > >   data B = B {
> > > > > > > >     b1 :: Maybe C
> > > > > > > >     ... }
> > > > > > > >
> > > > > > > > I retrieve it from network, files, i.e. external world,
> > > > > > > > then I validate it, report errors of some missing
> > > > > > > > fields, fix another one (which can be fixed, for
> > > > > > > > example, replace Nothing with `Just default_value` or
> > > > > > > > even I can fix `Just wrong` to `Just right`, etc, etc).
> > > > > > > > After all of this, I know that I have "clean" data, so
> > > > > > > > all my complex types now have `Just right_value`
> > > > > > > > fields. But I need to process them as optional, with
> > > > > > > > possible Nothing case! To avoid it I must create copies
> > > > > > > > of `A`, `B`, etc, where `a1`, `b1` will be `B`, `C`,
> > > > > > > > not `Maybe B`, `Maybe C`. Sure, it's not a case.
> > > > > > > >
> > > > > > > > After processing and filtering, I create, for example,
> > > > > > > > some resulting objects:
> > > > > > > >
> > > > > > > >   data Result {
> > > > > > > >     a :: A -- not Maybe!
> > > > > > > >     ... }
> > > > > > > >
> > > > > > > > And even more: `a::A` in `Result` (I know it, after
> > > > > > > > filtering) will not contain Nothings, only `Just
> > > > > > > > right_values`s.
> > > > > > > >
> > > > > > > > But each function which consumes `A` must do something
> > > > > > > > with possible Nothing values even after filtering and
> > > > > > > > fixing of `A`s.
> > > > > > > >
> > > > > > > > I have, for example, function:
> > > > > > > >
> > > > > > > >   createResults :: [A] -> [Result]
> > > > > > > >   createResults alst =
> > > > > > > >     ...
> > > > > > > >     case of (a1 theA) ->
> > > > > > > >       Just right_value -> ...
> > > > > > > >       Nothing ->
> > > > > > > >         logError
> > > > > > > >         undefined -- can not happen
> > > > > > > >
> > > > > > > > Fun here is: that it happens (I found bug in my
> > > > > > > > filtering code with this `undefined`). But now I
> > > > > > > > thought about it: what is the idiomatic way to solve
> > > > > > > > such situation? When you need to have:
> > > > > > > >
> > > > > > > >   - COMPLEX type WITH Maybes
> > > > > > > >   - the same type WITHOUT Maybes
> > > > > > > >
> > > > > > > > Alternative is to keep this Maybes to the very end of
> > > > > > > > processing, what I don't like. Or to have types copies,
> > > > > > > > which is more terrible, sure.
> > > > > > > >
> > > > > > > > PS. I threw IOs away to show only the crux of the
> > > > > > > > problem.
> > > > > > > >
> > > > > > > > ---
> > > > > > > > Cheers,
> > > > > > > >   Paul
> > > > > > > > _______________________________________________
> > > > > > > > Beginners mailing list
> > > > > > > > [hidden email]
> > > > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > > > > > >  
> > > > > >
> > > > > > _______________________________________________
> > > > > > Beginners mailing list
> > > > > > [hidden email]
> > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > > > >  
> > > >
> > > > _______________________________________________
> > > > Beginners mailing list
> > > > [hidden email]
> > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> > > >  
> >
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >  

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Sylvain Henry-2
In reply to this post by Baa
Hi,

You can use something similar to "Trees that grows" in GHC:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}

module Main where

import Data.Maybe

data Checked   = Checked   deriving (Show)
data Unchecked = Unchecked deriving (Show)

type family F a b :: * where
    F Unchecked b = Maybe b
    F Checked   b = b

-- data types are decorated with a phantom type indicating if they have
been checked
-- in which case "Maybe X" are replaced with "X" (see F above)
data A c = A
    { a1 :: F c (B c)
    }

data B c = B
    { b1 :: F c (C c)
    }

data C c = C
    { c1 :: F c Int
    }

deriving instance Show (F c (B c)) => Show (A c)
deriving instance Show (F c (C c)) => Show (B c)
deriving instance Show (F c Int)   => Show (C c)

class Checkable a where
    check :: a Unchecked -> a Checked

instance Checkable A where
    check (A mb) = A (check (fromJust mb))

instance Checkable B where
    check (B mc) = B (check (fromJust mc))

instance Checkable C where
    check (C mi) = C (fromJust mi)

main :: IO ()
main = do
    let
       a :: A Unchecked
       a = A (Just (B (Just (C (Just 10)))))

       a' :: A Checked
       a' = check a
    print a
    print a'


$> ./Test
A {a1 = Just (B {b1 = Just (C {c1 = Just 10})})}
A {a1 = B {b1 = C {c1 = 10}}}


Cheers,
Sylvain


On 06/07/2017 10:12, Baa wrote:

> Hello Dear List!
>
> Consider, I retrieve from external source some data. Internally it's
> represented as some complex type with `Maybe` fields, even more, some
> of fields are record types and have `Maybe` fields too. They are
> Maybe's because some information in this data can be missing (user
> error or it not very valuable and can be skipped):
>
>    data A = A {
>      a1 :: Maybe B
>      ... }
>    data B = B {
>      b1 :: Maybe C
>      ... }
>
> I retrieve it from network, files, i.e. external world, then I validate
> it, report errors of some missing fields, fix another one (which can be
> fixed, for example, replace Nothing with `Just default_value` or even I
> can fix `Just wrong` to `Just right`, etc, etc). After all of this, I
> know that I have "clean" data, so all my complex types now have `Just
> right_value` fields. But I need to process them as optional, with
> possible Nothing case! To avoid it I must create copies of `A`, `B`,
> etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure,
> it's not a case.
>
> After processing and filtering, I create, for example, some resulting
> objects:
>
>    data Result {
>      a :: A -- not Maybe!
>      ... }
>
> And even more: `a::A` in `Result` (I know it, after filtering) will not
> contain Nothings, only `Just right_values`s.
>
> But each function which consumes `A` must do something with possible
> Nothing values even after filtering and fixing of `A`s.
>
> I have, for example, function:
>
>    createResults :: [A] -> [Result]
>    createResults alst =
>      ...
>      case of (a1 theA) ->
>        Just right_value -> ...
>        Nothing ->
>          logError
>          undefined -- can not happen
>
> Fun here is: that it happens (I found bug in my filtering
> code with this `undefined`). But now I thought about it: what is the
> idiomatic way to solve such situation? When you need to have:
>
>    - COMPLEX type WITH Maybes
>    - the same type WITHOUT Maybes
>
> Alternative is to keep this Maybes to the very end of processing, what I
> don't like. Or to have types copies, which is more terrible, sure.
>
> PS. I threw IOs away to show only the crux of the problem.
>
> ---
> Cheers,
>    Paul
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Imants Cekusins
> "Trees that grows"

this (type families), or Tagged

data Checked = Checked

  Tagged Checked a



On 6 July 2017 at 16:09, Sylvain Henry <[hidden email]> wrote:
Hi,

You can use something similar to "Trees that grows" in GHC:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}

module Main where

import Data.Maybe

data Checked   = Checked   deriving (Show)
data Unchecked = Unchecked deriving (Show)

type family F a b :: * where
   F Unchecked b = Maybe b
   F Checked   b = b

-- data types are decorated with a phantom type indicating if they have been checked
-- in which case "Maybe X" are replaced with "X" (see F above)
data A c = A
   { a1 :: F c (B c)
   }

data B c = B
   { b1 :: F c (C c)
   }

data C c = C
   { c1 :: F c Int
   }

deriving instance Show (F c (B c)) => Show (A c)
deriving instance Show (F c (C c)) => Show (B c)
deriving instance Show (F c Int)   => Show (C c)

class Checkable a where
   check :: a Unchecked -> a Checked

instance Checkable A where
   check (A mb) = A (check (fromJust mb))

instance Checkable B where
   check (B mc) = B (check (fromJust mc))

instance Checkable C where
   check (C mi) = C (fromJust mi)

main :: IO ()
main = do
   let
      a :: A Unchecked
      a = A (Just (B (Just (C (Just 10)))))

      a' :: A Checked
      a' = check a
   print a
   print a'


$> ./Test
A {a1 = Just (B {b1 = Just (C {c1 = Just 10})})}
A {a1 = B {b1 = C {c1 = 10}}}


Cheers,
Sylvain



On 06/07/2017 10:12, Baa wrote:
Hello Dear List!

Consider, I retrieve from external source some data. Internally it's
represented as some complex type with `Maybe` fields, even more, some
of fields are record types and have `Maybe` fields too. They are
Maybe's because some information in this data can be missing (user
error or it not very valuable and can be skipped):

   data A = A {
     a1 :: Maybe B
     ... }
   data B = B {
     b1 :: Maybe C
     ... }

I retrieve it from network, files, i.e. external world, then I validate
it, report errors of some missing fields, fix another one (which can be
fixed, for example, replace Nothing with `Just default_value` or even I
can fix `Just wrong` to `Just right`, etc, etc). After all of this, I
know that I have "clean" data, so all my complex types now have `Just
right_value` fields. But I need to process them as optional, with
possible Nothing case! To avoid it I must create copies of `A`, `B`,
etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure,
it's not a case.

After processing and filtering, I create, for example, some resulting
objects:

   data Result {
     a :: A -- not Maybe!
     ... }

And even more: `a::A` in `Result` (I know it, after filtering) will not
contain Nothings, only `Just right_values`s.

But each function which consumes `A` must do something with possible
Nothing values even after filtering and fixing of `A`s.

I have, for example, function:

   createResults :: [A] -> [Result]
   createResults alst =
     ...
     case of (a1 theA) ->
       Just right_value -> ...
       Nothing ->
         logError
         undefined -- can not happen

Fun here is: that it happens (I found bug in my filtering
code with this `undefined`). But now I thought about it: what is the
idiomatic way to solve such situation? When you need to have:

   - COMPLEX type WITH Maybes
   - the same type WITHOUT Maybes

Alternative is to keep this Maybes to the very end of processing, what I
don't like. Or to have types copies, which is more terrible, sure.

PS. I threw IOs away to show only the crux of the problem.

---
Cheers,
   Paul
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Baa
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Get rid of Maybes in complex types

Baa
In reply to this post by Sylvain Henry-2
Hello, Sylvain. Hmm, it's very interesting. Funny is that I already
have tagged items but tags are run-time values, not compile time
(types) :-)  but this is a different.

Problem was to make:

  A-with-maybes -> A-without-maybes

Phantom type as flag and "clearing" of Maybe with

  family-type-with-maybes -> family-type-without-maybes

looks promisingly. Another advantage, as I understand, is that I
continue to use Just as a constructor for `a1` value, without to wrap it
in something else, right?

This seems to be a solution.

Thank you and all others for your answers!!

---
Best regards,
  Paul


В Thu, 6 Jul 2017 15:09:17 +0200
Sylvain Henry <[hidden email]> wrote:

> Hi,
>
> You can use something similar to "Trees that grows" in GHC:
>
> {-# LANGUAGE TypeFamilies #-}
> {-# LANGUAGE StandaloneDeriving #-}
> {-# LANGUAGE FlexibleContexts #-}
> {-# LANGUAGE UndecidableInstances #-}
>
> module Main where
>
> import Data.Maybe
>
> data Checked   = Checked   deriving (Show)
> data Unchecked = Unchecked deriving (Show)
>
> type family F a b :: * where
>     F Unchecked b = Maybe b
>     F Checked   b = b
>
> -- data types are decorated with a phantom type indicating if they
> have been checked
> -- in which case "Maybe X" are replaced with "X" (see F above)
> data A c = A
>     { a1 :: F c (B c)
>     }
>
> data B c = B
>     { b1 :: F c (C c)
>     }
>
> data C c = C
>     { c1 :: F c Int
>     }
>
> deriving instance Show (F c (B c)) => Show (A c)
> deriving instance Show (F c (C c)) => Show (B c)
> deriving instance Show (F c Int)   => Show (C c)
>
> class Checkable a where
>     check :: a Unchecked -> a Checked
>
> instance Checkable A where
>     check (A mb) = A (check (fromJust mb))
>
> instance Checkable B where
>     check (B mc) = B (check (fromJust mc))
>
> instance Checkable C where
>     check (C mi) = C (fromJust mi)
>
> main :: IO ()
> main = do
>     let
>        a :: A Unchecked
>        a = A (Just (B (Just (C (Just 10)))))
>
>        a' :: A Checked
>        a' = check a
>     print a
>     print a'
>
>
> $> ./Test  
> A {a1 = Just (B {b1 = Just (C {c1 = Just 10})})}
> A {a1 = B {b1 = C {c1 = 10}}}
>
>
> Cheers,
> Sylvain
>
>
> On 06/07/2017 10:12, Baa wrote:
> > Hello Dear List!
> >
> > Consider, I retrieve from external source some data. Internally it's
> > represented as some complex type with `Maybe` fields, even more,
> > some of fields are record types and have `Maybe` fields too. They
> > are Maybe's because some information in this data can be missing
> > (user error or it not very valuable and can be skipped):
> >
> >    data A = A {
> >      a1 :: Maybe B
> >      ... }
> >    data B = B {
> >      b1 :: Maybe C
> >      ... }
> >
> > I retrieve it from network, files, i.e. external world, then I
> > validate it, report errors of some missing fields, fix another one
> > (which can be fixed, for example, replace Nothing with `Just
> > default_value` or even I can fix `Just wrong` to `Just right`, etc,
> > etc). After all of this, I know that I have "clean" data, so all my
> > complex types now have `Just right_value` fields. But I need to
> > process them as optional, with possible Nothing case! To avoid it I
> > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`,
> > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case.
> >
> > After processing and filtering, I create, for example, some
> > resulting objects:
> >
> >    data Result {
> >      a :: A -- not Maybe!
> >      ... }
> >
> > And even more: `a::A` in `Result` (I know it, after filtering) will
> > not contain Nothings, only `Just right_values`s.
> >
> > But each function which consumes `A` must do something with possible
> > Nothing values even after filtering and fixing of `A`s.
> >
> > I have, for example, function:
> >
> >    createResults :: [A] -> [Result]
> >    createResults alst =
> >      ...
> >      case of (a1 theA) ->
> >        Just right_value -> ...
> >        Nothing ->
> >          logError
> >          undefined -- can not happen
> >
> > Fun here is: that it happens (I found bug in my filtering
> > code with this `undefined`). But now I thought about it: what is the
> > idiomatic way to solve such situation? When you need to have:
> >
> >    - COMPLEX type WITH Maybes
> >    - the same type WITHOUT Maybes
> >
> > Alternative is to keep this Maybes to the very end of processing,
> > what I don't like. Or to have types copies, which is more terrible,
> > sure.
> >
> > PS. I threw IOs away to show only the crux of the problem.
> >
> > ---
> > Cheers,
> >    Paul
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners 
>
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Loading...