Maybe and Just

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Shishir Srivastava
Hi,

After reading and re-reading the haskell tutorials I don't happen to see a
very convincing or appealing reason for having these data types.

Can anyone please explain where Maybe and Just provide the sort of
functionality that cannot be achieved in other languages which don't have
these kind.

Thanks,
Shishir Srivastava
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/926492ee/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Michael Alan Dorman
Shishir Srivastava <shishir.srivastava at gmail.com> writes:
> After reading and re-reading the haskell tutorials I don't happen to
> see a very convincing or appealing reason for having these data
> types.

To be clear: Maybe is the data *type*.  Just and Nothing are its data
*constructors*.

> Can anyone please explain where Maybe and Just provide the sort of
> functionality that cannot be achieved in other languages which don't
> have these kind.

The functionality can be achieved in other languages, certainly.  The
question is whether the clarity and safety is also achieved.

When I see (as a totally contrived example):

  fopen :: Maybe FileHandle

I know that that function may not be able to return a FileHandle value
all the time.  The compiler will, in fact, nag me if I do not write the
code that calls it in such a way that it acknowledges that possibility.

When I see:

  FILE * fopen ( const char * filename, const char * mode );

It is not immediately clear whether that can fail.  Sure, we can make
that inference, based on what we know about filesystems, etc., but the
compiler is never going to complain if I ignore the possibility.

In my experience, programmers in many languages end up resorting to
convention to try and work around these sorts of ambiguities.  Large
projects have strategies for naming functions that try to pass along
information out of band, or languages have a pervasive culture of "lint"
tools that try to use heuristics to make up for what the type system
doesn't make simple.

That said, I know that doing Maybe sorts of things in languages that
don't have, say, pattern matching, or the idea of a "failure monad",
gets to be a drag very quickly---manually unwrapping things is at best
awkward, having to re-wrap them just to unwrap them again in a sequence
of computations quickly leads one to believe "it's just not worth
it"---or you resort to exception handling, which has its own challenges
to do well.

Mike.

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Lyndon Maydwell
In reply to this post by Shishir Srivastava
Hi Shishir,


Indeed, Maybe doesn't grant you additional operational functionality that
other languages lack. Most use-cases of Maybe can be matched in nearly all
mainstream languages through the use of NULL.

Maybe illustrates a desired lack of functionality in cases where it is
absent.

For example, in Java:

public static Integer myMethod(Integer a, Integer b) {
  // body}


What do we know about this method from the signature?

You would think it is a method that takes two integers and returns an
integer, but really it could take NULLs too, and could possibly return a
NULL.

Here is the equivalent Haskell signature:

myMethod :: Maybe Integer -> Maybe Integer -> IO (Maybe Integer)


We can see that Maybe allows us to replicate the possibility of NULL values
from other languages... But how is that special since other languages
already have this built-in.

Now look at the following Haskell signature:

myMethod :: Integer -> Integer -> Integer


Now what do we know about this?

We know that it takes two Integers and returns an Integer.

This is the power that comes from having Maybe as the canonical way to
represent the possibility of missing values.


On Thu, Mar 26, 2015 at 9:06 PM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Hi,
>
> After reading and re-reading the haskell tutorials I don't happen to see a
> very convincing or appealing reason for having these data types.
>
> Can anyone please explain where Maybe and Just provide the sort of
> functionality that cannot be achieved in other languages which don't have
> these kind.
>
> Thanks,
> Shishir Srivastava
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/624cc397/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Mike Meyer
In reply to this post by Shishir Srivastava
On Thu, Mar 26, 2015 at 5:06 AM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Hi,
>
> After reading and re-reading the haskell tutorials I don't happen to see a
> very convincing or appealing reason for having these data types.
>
> Can anyone please explain where Maybe and Just provide the sort of
> functionality that cannot be achieved in other languages which don't have
> these kind.
>

When a function fails to produce the return value, it can either return a
distinguished value (a NULL pointer, or -1 to signal an error, or ...) or
raise an exception. The latter is sufficiently clumsy that it's not
uncommon to see languages with two versions of some functions: one that
raises an exception, and one that returns a distinguished value.

Haskell uses the Maybe type for the distinguished value, raising it to the
type level. If I call a function that expects a value that is NOT the
distinguished value (a valid pointer, or a valid array index, or ...) in
languages without something like a Maybe type, I find out about it when my
unit tests fail if I'm lucky, or I just  get the wrong answer if I'm not.
When I call a function that expects an X with a value of type Maybe X in
Haskell, it's a type error at compile time.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/2c882605/attachment-0001.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Frerich Raabe
In reply to this post by Shishir Srivastava
Hi,

On 2015-03-26 11:06, Shishir Srivastava wrote:
> After reading and re-reading the haskell tutorials I don't happen to see a
> very convincing or appealing reason for having these data types.

First of all, only one of them is a type (or a 'type constructor'): "Maybe".
"Just" on the other hand is a "data constructor", i.e. "Just 'x'" will yield
a value of type "Maybe Char".

> Can anyone please explain where Maybe and Just provide the sort of
> functionality that cannot be achieved in other languages which don't have
> these kind.

They don't provide anything which other languages cannot achieve. 'Maybe'
values merely indicate that you *maybe* get a value. This is useful for
functions which might not be able to yield a meaningful result. Consider a
'safeHead' function which works like 'head', returning the first element of a
given list. What should it do for empty lists?

Something like 'Maybe' is useful because it

1. Makes potential errors clearly visible in the type system: If a function
returns a 'Maybe Char', you know that it possible won't yield a Char (but
rather 'Nothing'). Raising an exception is totally opaque to the caller.

2. Clearly separates the values which might represent failures from those
which don't. Contrast this with e.g. Java, where every object of every type
can be null. If every value is potentially 'null', you either have to check
using if() everywhere or use assertions. With 'Maybe', the null'ness can be
asserted by the compiler.

3. Relieves other types from having an explicit 'Invalid' value. Consider:

   data Color = Red | Green | Blue | Invalid

   -- Parses a color string; yields 'Invalid' if the string is malformed
   parseColor :: String -> Color
   parseColor = undefind

With a setup like this, *every* code dealing with 'Color' values will have to
be able to handle 'Invalid' colors. It ripples through the system. OTOH,
something like

   data Color = Red | Green | Blue

   -- Parses a color string; yields 'Nothing' if the string is malformed
   parseColor :: String -> Maybe Color
   parseColor = undefined

Clearly separates the valid colors, such that only the caller of 'parseColor'
only has to check for 'Just x' values - and if it got one, it can pass the
'x' value to other code.

For what it's worth, other languages have similiar concepts. For instance,
C++ programmers can use 'boost::optional' (which, alas, didn't make it into
C++14).

--
Frerich Raabe - raabe at froglogic.com
www.froglogic.com - Multi-Platform GUI Testing

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Joel Neely
In reply to this post by Shishir Srivastava
Hi, Shishir,

As a recovering complexity addict (i.e. Java programmer ;-), I'd put it
this way.

There are many methods (on many types) that can either succeed and return a
meaningful value, or be unable to fulfill the intent of the caller's
request. Example include indexOf on String,  get on Map, and read on a
Reader. Every time such a partial function scenario occurs, the author must
decide what to do if the intent can't be fulfilled. That freedom of choice
has led to a proliferation of techniques.


   - indexOf returns -1, which is a valid int, but not a valid position
   within a string.
   - get returns null, which is the only value common to all reference
   types that means 'I have nothing'. Of course, that also prevents one from
   storing null in a Map and simply retrieving it. Worse, if that result is
   passed along elsewhere, one can eventually receive a NullPointerException
   occurring in a completely different part of the code.
   - And, *horrors!*, read responds in a totally different way, by forcing
   the caller to "jump" somewhere.


Maybe provides a general, reusable solution to all such cases.

   - It allows one to "stretch" any type to include an extra "out of band"
   value.
   - The type declaration clearly (uniformly) notifies anyone else that the
   function may have to return "lack of result".
   - The type system prevents a caller from simply assuming that a result
   is present, and then accidentally propagating failure.
   - Because Maybe is an instance of Functor, one can use map to safely
   apply a function (or do nothing gracefully) without littering the calling
   code with if-statements.
   - etc.


I don't think of Maybe as enabling a *computation* that is impossible
otherwise, but I do regard it as providing a *consistency and simplicity*
that is otherwise not present.

Hope this helps,
Joel


On Thu, Mar 26, 2015 at 5:06 AM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Hi,
>
> After reading and re-reading the haskell tutorials I don't happen to see a
> very convincing or appealing reason for having these data types.
>
> Can anyone please explain where Maybe and Just provide the sort of
> functionality that cannot be achieved in other languages which don't have
> these kind.
>
> Thanks,
> Shishir Srivastava
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>


--
Beauty of style and harmony and grace and good rhythm depend on simplicity.
- Plato
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/7a3f42cc/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Shishir Srivastava
In reply to this post by Michael Alan Dorman
ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
defined like this

data Maybe a = a | Nothing

what's the point in having 'Just' keyword ?

Shishir


On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
mdorman at ironicdesign.com> wrote:

> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
> > After reading and re-reading the haskell tutorials I don't happen to
> > see a very convincing or appealing reason for having these data
> > types.
>
> To be clear: Maybe is the data *type*.  Just and Nothing are its data
> *constructors*.
>
> > Can anyone please explain where Maybe and Just provide the sort of
> > functionality that cannot be achieved in other languages which don't
> > have these kind.
>
> The functionality can be achieved in other languages, certainly.  The
> question is whether the clarity and safety is also achieved.
>
> When I see (as a totally contrived example):
>
>   fopen :: Maybe FileHandle
>
> I know that that function may not be able to return a FileHandle value
> all the time.  The compiler will, in fact, nag me if I do not write the
> code that calls it in such a way that it acknowledges that possibility.
>
> When I see:
>
>   FILE * fopen ( const char * filename, const char * mode );
>
> It is not immediately clear whether that can fail.  Sure, we can make
> that inference, based on what we know about filesystems, etc., but the
> compiler is never going to complain if I ignore the possibility.
>
> In my experience, programmers in many languages end up resorting to
> convention to try and work around these sorts of ambiguities.  Large
> projects have strategies for naming functions that try to pass along
> information out of band, or languages have a pervasive culture of "lint"
> tools that try to use heuristics to make up for what the type system
> doesn't make simple.
>
> That said, I know that doing Maybe sorts of things in languages that
> don't have, say, pattern matching, or the idea of a "failure monad",
> gets to be a drag very quickly---manually unwrapping things is at best
> awkward, having to re-wrap them just to unwrap them again in a sequence
> of computations quickly leads one to believe "it's just not worth
> it"---or you resort to exception handling, which has its own challenges
> to do well.
>
> Mike.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/f3792e14/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Brandon Allbery
On Thu, Mar 26, 2015 at 11:26 AM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
> defined like this
>
> data Maybe a = a | Nothing
>

Because type inference won't work if you don't have a distinction between
an a and a Maybe a. Also, you end up back where you started --- there's a
distinguished (non)value that appears to be a value of the type, which
leaves you no better off than with C's NULL or Perl's undef, losing the
type safety of "this can't fail" vs. "this may fail and you must deal with
the failure somehow".

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b at gmail.com                                  ballbery at sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/e6dbc786/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Corentin Dupont
In reply to this post by Shishir Srivastava
Hi Shishir,
I think that's a legitimate question.

By writing

data Maybe a = a | Nothing

you are saying that the type of the left hand side of the = is the same
that right hand side (you are defining a type basically).
Also you can only sum things of the same type.
So you are saying:
type "Maybe a" = type "a"
Which is wrong.
That's why "a" should be wrapped into something:
type of "Just a" is indeed "Maybe a".

"Just" is a type constructor:
Just :: a -> Maybe a
It allows you to build the Maybe.

Said that, "Just" is a vocabulary choice.
Personally I prefer the name choices of OCaml, Rust, Scala etc.: Option a =
None | Some a



On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
> defined like this
>
> data Maybe a = a | Nothing
>
> what's the point in having 'Just' keyword ?
>
> Shishir
>
>
> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
> mdorman at ironicdesign.com> wrote:
>
>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>> > After reading and re-reading the haskell tutorials I don't happen to
>> > see a very convincing or appealing reason for having these data
>> > types.
>>
>> To be clear: Maybe is the data *type*.  Just and Nothing are its data
>> *constructors*.
>>
>> > Can anyone please explain where Maybe and Just provide the sort of
>> > functionality that cannot be achieved in other languages which don't
>> > have these kind.
>>
>> The functionality can be achieved in other languages, certainly.  The
>> question is whether the clarity and safety is also achieved.
>>
>> When I see (as a totally contrived example):
>>
>>   fopen :: Maybe FileHandle
>>
>> I know that that function may not be able to return a FileHandle value
>> all the time.  The compiler will, in fact, nag me if I do not write the
>> code that calls it in such a way that it acknowledges that possibility.
>>
>> When I see:
>>
>>   FILE * fopen ( const char * filename, const char * mode );
>>
>> It is not immediately clear whether that can fail.  Sure, we can make
>> that inference, based on what we know about filesystems, etc., but the
>> compiler is never going to complain if I ignore the possibility.
>>
>> In my experience, programmers in many languages end up resorting to
>> convention to try and work around these sorts of ambiguities.  Large
>> projects have strategies for naming functions that try to pass along
>> information out of band, or languages have a pervasive culture of "lint"
>> tools that try to use heuristics to make up for what the type system
>> doesn't make simple.
>>
>> That said, I know that doing Maybe sorts of things in languages that
>> don't have, say, pattern matching, or the idea of a "failure monad",
>> gets to be a drag very quickly---manually unwrapping things is at best
>> awkward, having to re-wrap them just to unwrap them again in a sequence
>> of computations quickly leads one to believe "it's just not worth
>> it"---or you resort to exception handling, which has its own challenges
>> to do well.
>>
>> Mike.
>>
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/a09cd3c1/attachment-0001.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

emacstheviking
In reply to this post by Michael Alan Dorman
For what its worth I wrote this a while back, a hopeless attempt to do
something "monad like" in PHP but reading it again..... well, it's no
wonder I like Haskell more than I like having to use PHP!

http://objitsu.blogspot.co.uk/2013/01/php-and-maybe-miserable-monads.html



On 26 March 2015 at 10:26, Michael Alan Dorman <mdorman at ironicdesign.com>
wrote:

> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
> > After reading and re-reading the haskell tutorials I don't happen to
> > see a very convincing or appealing reason for having these data
> > types.
>
> To be clear: Maybe is the data *type*.  Just and Nothing are its data
> *constructors*.
>
> > Can anyone please explain where Maybe and Just provide the sort of
> > functionality that cannot be achieved in other languages which don't
> > have these kind.
>
> The functionality can be achieved in other languages, certainly.  The
> question is whether the clarity and safety is also achieved.
>
> When I see (as a totally contrived example):
>
>   fopen :: Maybe FileHandle
>
> I know that that function may not be able to return a FileHandle value
> all the time.  The compiler will, in fact, nag me if I do not write the
> code that calls it in such a way that it acknowledges that possibility.
>
> When I see:
>
>   FILE * fopen ( const char * filename, const char * mode );
>
> It is not immediately clear whether that can fail.  Sure, we can make
> that inference, based on what we know about filesystems, etc., but the
> compiler is never going to complain if I ignore the possibility.
>
> In my experience, programmers in many languages end up resorting to
> convention to try and work around these sorts of ambiguities.  Large
> projects have strategies for naming functions that try to pass along
> information out of band, or languages have a pervasive culture of "lint"
> tools that try to use heuristics to make up for what the type system
> doesn't make simple.
>
> That said, I know that doing Maybe sorts of things in languages that
> don't have, say, pattern matching, or the idea of a "failure monad",
> gets to be a drag very quickly---manually unwrapping things is at best
> awkward, having to re-wrap them just to unwrap them again in a sequence
> of computations quickly leads one to believe "it's just not worth
> it"---or you resort to exception handling, which has its own challenges
> to do well.
>
> Mike.
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/229f12d5/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Corentin Dupont
In reply to this post by Corentin Dupont
Not really, when you define the type "Maybe a":

data Maybe a = Just a | Nothing

Haskell is creating automatically two functions for you:

Just :: a -> Maybe a
Nothing :: Maybe a

In the first case, you can think of "Just" and "Nothing" as a sort of tag
identifying which element of the sum you have.
It the second case it's a function, with the same name.
A more informed person than me could say if they are indeed separated of if
they are the same thing in GHC...


On Thu, Mar 26, 2015 at 5:34 PM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> isn't that then cyclic dependency between 'Maybe' and 'Just' ...where the
> first one is defined in terms of second and vice-versa...?
>
> Shishir
>
>
> On Thu, Mar 26, 2015 at 3:48 PM, Corentin Dupont <
> corentin.dupont at gmail.com> wrote:
>
>> Hi Shishir,
>> I think that's a legitimate question.
>>
>> By writing
>>
>> data Maybe a = a | Nothing
>>
>> you are saying that the type of the left hand side of the = is the same
>> that right hand side (you are defining a type basically).
>> Also you can only sum things of the same type.
>> So you are saying:
>> type "Maybe a" = type "a"
>> Which is wrong.
>> That's why "a" should be wrapped into something:
>> type of "Just a" is indeed "Maybe a".
>>
>> "Just" is a type constructor:
>> Just :: a -> Maybe a
>> It allows you to build the Maybe.
>>
>> Said that, "Just" is a vocabulary choice.
>> Personally I prefer the name choices of OCaml, Rust, Scala etc.: Option
>> a = None | Some a
>>
>>
>>
>> On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
>> shishir.srivastava at gmail.com> wrote:
>>
>>> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
>>> defined like this
>>>
>>> data Maybe a = a | Nothing
>>>
>>> what's the point in having 'Just' keyword ?
>>>
>>> Shishir
>>>
>>>
>>> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
>>> mdorman at ironicdesign.com> wrote:
>>>
>>>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>>>> > After reading and re-reading the haskell tutorials I don't happen to
>>>> > see a very convincing or appealing reason for having these data
>>>> > types.
>>>>
>>>> To be clear: Maybe is the data *type*.  Just and Nothing are its data
>>>> *constructors*.
>>>>
>>>> > Can anyone please explain where Maybe and Just provide the sort of
>>>> > functionality that cannot be achieved in other languages which don't
>>>> > have these kind.
>>>>
>>>> The functionality can be achieved in other languages, certainly.  The
>>>> question is whether the clarity and safety is also achieved.
>>>>
>>>> When I see (as a totally contrived example):
>>>>
>>>>   fopen :: Maybe FileHandle
>>>>
>>>> I know that that function may not be able to return a FileHandle value
>>>> all the time.  The compiler will, in fact, nag me if I do not write the
>>>> code that calls it in such a way that it acknowledges that possibility.
>>>>
>>>> When I see:
>>>>
>>>>   FILE * fopen ( const char * filename, const char * mode );
>>>>
>>>> It is not immediately clear whether that can fail.  Sure, we can make
>>>> that inference, based on what we know about filesystems, etc., but the
>>>> compiler is never going to complain if I ignore the possibility.
>>>>
>>>> In my experience, programmers in many languages end up resorting to
>>>> convention to try and work around these sorts of ambiguities.  Large
>>>> projects have strategies for naming functions that try to pass along
>>>> information out of band, or languages have a pervasive culture of "lint"
>>>> tools that try to use heuristics to make up for what the type system
>>>> doesn't make simple.
>>>>
>>>> That said, I know that doing Maybe sorts of things in languages that
>>>> don't have, say, pattern matching, or the idea of a "failure monad",
>>>> gets to be a drag very quickly---manually unwrapping things is at best
>>>> awkward, having to re-wrap them just to unwrap them again in a sequence
>>>> of computations quickly leads one to believe "it's just not worth
>>>> it"---or you resort to exception handling, which has its own challenges
>>>> to do well.
>>>>
>>>> Mike.
>>>>
>>>
>>>
>>> _______________________________________________
>>> Beginners mailing list
>>> Beginners at haskell.org
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150326/ee19fe82/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Martin Drautzburg
In reply to this post by Shishir Srivastava
Am 03/26/2015 um 11:06 AM schrieb Shishir Srivastava:
> Hi,
>
> After reading and re-reading the haskell tutorials I don't happen to see a very convincing or appealing reason for
> having these data types.
>
> Can anyone please explain where Maybe and Just provide the sort of functionality that cannot be achieved in other
> languages which don't have these kind.

My intuition goes like that:

"Maybe" is like "nullable" (which doesn't really exist, but you sure can imagine what it means). In many programming
languages a variable of any type can contain "null", i.e. every type is nullable. This means that any function accepting
one of these types as a parameter must be prepared to see a null. You end up with many checks like

        if (x==null) {return null;}

Not so in haskell. An Int is really an Int and Ints cannot be null. Functions accepting Ints don't have to check for null.

But you can beef up any datatype to be nullable. You can create a TYPE "nullable Int" which would be called "Maybe Int"
in Haskell. Just like "nullable" alone, Maybe itself is not a type, but an up-beefer of another type. There are no
values of type Maybe, but only of Maybe Int, Maybe String etc. In that respect maybe is like "List". There are no values
of type "List", but only of List of Int, List of String. List is an up-beefer too (written as [] in Haskell)

Obviously there needs to be a distinct VALUE for "null". In Haskell this value is called "Nothing".

For the non-null VALUES you could think about  writing them verbatim, like "42". But from just looking at 42, you
couldn't tell what type it is. It could be an Int or a Maybe Int. This problem is somewhat akin to writing 42.0 when you
want to make sure it is a float (in imperative languages), or 42L to indicate it is a long.

So in the same vein, you distinguish an Int (42) from a Maybe Int (Just 42). Just 42 is a value of type Maybe Int, which
just (sic!) happens not to be null, but it is still not a plain Int, but a Maybe Int. Like 42.0 is a float which happens
not to have any digits after the decimal point but also is not a plain Int but a float.



Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Greg Graham
On Thu, Mar 26, 2015 at 4:04 PM, martin <martin.drautzburg at web.de> wrote:
> Am 03/26/2015 um 11:06 AM schrieb Shishir Srivastava:
>> Hi,
>>
>> After reading and re-reading the haskell tutorials I don't happen to see a very convincing or appealing reason for
>> having these data types.
>>
>> Can anyone please explain where Maybe and Just provide the sort of functionality that cannot be achieved in other
>> languages which don't have these kind.

I'm reading the little book, _Maybe Haskell_ [1], and I'm finding it
very helpful on this topic. The whole Maybe paradigm is one of the
reasons I decided to learn Haskell.

I had previously started learning Go, and although I was initially
attracted by its simplicity, I came to dislike how it used return
values to indicate errors. Go typically returns a pair of values from
operations that can fail. One value is the normal return value, and
the other is an error code. At first look, I thought it was similar to
Haskell's Maybe. However, after doing a little Go programming, I
realized there's a big difference. The error codes in Go can be
ignored, sometimes accidentally, but you can't ignore Haskell's Maybe.
Sure, it's possible to respond poorly, but you do have to respond, all
because (Just 42) is not the same thing as (42).

1: https://robots.thoughtbot.com/maybe-haskell-our-newest-book

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Shishir Srivastava
In reply to this post by Corentin Dupont
Sorry, but I still have some grudges so to say with the way 'Maybe' is
defined.

By definition '*Maybe*' takes a type parameter which I will denote here as '
*tp*' for the sake of clarity like below -

data Maybe tp = Just tp | Nothing

Therefore '*tp*' is not representing a value perse such as '3' or 'XYZ' etc
but a data type such as '*Int*', '*Char*' etc.

But when we have to create a data type of '*Maybe*' we write '*Just 3*' and
not '*Just Int*' or '*Just Char*' which is how it's defined in the
definition (i.e. '*Just tp*' ) .

It is this discrepancy in definition and the actual value creation which is
slightly troubling me.

Thanks,
Shishir

Shishir Srivastava
 +44 (0) 750 127 5019


On Thu, Mar 26, 2015 at 5:31 PM, Corentin Dupont <corentin.dupont at gmail.com>
wrote:

> Not really, when you define the type "Maybe a":
>
> data Maybe a = Just a | Nothing
>
> Haskell is creating automatically two functions for you:
>
> Just :: a -> Maybe a
> Nothing :: Maybe a
>
> In the first case, you can think of "Just" and "Nothing" as a sort of tag
> identifying which element of the sum you have.
> It the second case it's a function, with the same name.
> A more informed person than me could say if they are indeed separated of
> if they are the same thing in GHC...
>
>
> On Thu, Mar 26, 2015 at 5:34 PM, Shishir Srivastava <
> shishir.srivastava at gmail.com> wrote:
>
>> isn't that then cyclic dependency between 'Maybe' and 'Just' ...where the
>> first one is defined in terms of second and vice-versa...?
>>
>> Shishir
>>
>>
>> On Thu, Mar 26, 2015 at 3:48 PM, Corentin Dupont <
>> corentin.dupont at gmail.com> wrote:
>>
>>> Hi Shishir,
>>> I think that's a legitimate question.
>>>
>>> By writing
>>>
>>> data Maybe a = a | Nothing
>>>
>>> you are saying that the type of the left hand side of the = is the same
>>> that right hand side (you are defining a type basically).
>>> Also you can only sum things of the same type.
>>> So you are saying:
>>> type "Maybe a" = type "a"
>>> Which is wrong.
>>> That's why "a" should be wrapped into something:
>>> type of "Just a" is indeed "Maybe a".
>>>
>>> "Just" is a type constructor:
>>> Just :: a -> Maybe a
>>> It allows you to build the Maybe.
>>>
>>> Said that, "Just" is a vocabulary choice.
>>> Personally I prefer the name choices of OCaml, Rust, Scala etc.: Option
>>> a = None | Some a
>>>
>>>
>>>
>>> On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
>>> shishir.srivastava at gmail.com> wrote:
>>>
>>>> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
>>>> defined like this
>>>>
>>>> data Maybe a = a | Nothing
>>>>
>>>> what's the point in having 'Just' keyword ?
>>>>
>>>> Shishir
>>>>
>>>>
>>>> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
>>>> mdorman at ironicdesign.com> wrote:
>>>>
>>>>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>>>>> > After reading and re-reading the haskell tutorials I don't happen to
>>>>> > see a very convincing or appealing reason for having these data
>>>>> > types.
>>>>>
>>>>> To be clear: Maybe is the data *type*.  Just and Nothing are its data
>>>>> *constructors*.
>>>>>
>>>>> > Can anyone please explain where Maybe and Just provide the sort of
>>>>> > functionality that cannot be achieved in other languages which don't
>>>>> > have these kind.
>>>>>
>>>>> The functionality can be achieved in other languages, certainly.  The
>>>>> question is whether the clarity and safety is also achieved.
>>>>>
>>>>> When I see (as a totally contrived example):
>>>>>
>>>>>   fopen :: Maybe FileHandle
>>>>>
>>>>> I know that that function may not be able to return a FileHandle value
>>>>> all the time.  The compiler will, in fact, nag me if I do not write the
>>>>> code that calls it in such a way that it acknowledges that possibility.
>>>>>
>>>>> When I see:
>>>>>
>>>>>   FILE * fopen ( const char * filename, const char * mode );
>>>>>
>>>>> It is not immediately clear whether that can fail.  Sure, we can make
>>>>> that inference, based on what we know about filesystems, etc., but the
>>>>> compiler is never going to complain if I ignore the possibility.
>>>>>
>>>>> In my experience, programmers in many languages end up resorting to
>>>>> convention to try and work around these sorts of ambiguities.  Large
>>>>> projects have strategies for naming functions that try to pass along
>>>>> information out of band, or languages have a pervasive culture of
>>>>> "lint"
>>>>> tools that try to use heuristics to make up for what the type system
>>>>> doesn't make simple.
>>>>>
>>>>> That said, I know that doing Maybe sorts of things in languages that
>>>>> don't have, say, pattern matching, or the idea of a "failure monad",
>>>>> gets to be a drag very quickly---manually unwrapping things is at best
>>>>> awkward, having to re-wrap them just to unwrap them again in a sequence
>>>>> of computations quickly leads one to believe "it's just not worth
>>>>> it"---or you resort to exception handling, which has its own challenges
>>>>> to do well.
>>>>>
>>>>> Mike.
>>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Beginners mailing list
>>>> Beginners at haskell.org
>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150327/afe0f16c/attachment-0001.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Corentin Dupont
You're right, "Just" is used at two different levels, it's just that it
have the same name is both cases.
One is at type level, the other at value level.
Since this is two separated levels, there is no risk of confusion and
having the same name is fine.

To be clear, you can write:

data Maybe tp = Just Int | Nothing

Then use it as:

my_value = Just 3

On Fri, Mar 27, 2015 at 10:44 AM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Sorry, but I still have some grudges so to say with the way 'Maybe' is
> defined.
>
> By definition '*Maybe*' takes a type parameter which I will denote here
> as '*tp*' for the sake of clarity like below -
>
> data Maybe tp = Just tp | Nothing
>
> Therefore '*tp*' is not representing a value perse such as '3' or 'XYZ'
> etc but a data type such as '*Int*', '*Char*' etc.
>
> But when we have to create a data type of '*Maybe*' we write '*Just 3*'
> and not '*Just Int*' or '*Just Char*' which is how it's defined in the
> definition (i.e. '*Just tp*' ) .
>
> It is this discrepancy in definition and the actual value creation which
> is slightly troubling me.
>
> Thanks,
> Shishir
>
> Shishir Srivastava
>  +44 (0) 750 127 5019
>
>
> On Thu, Mar 26, 2015 at 5:31 PM, Corentin Dupont <
> corentin.dupont at gmail.com> wrote:
>
>> Not really, when you define the type "Maybe a":
>>
>> data Maybe a = Just a | Nothing
>>
>> Haskell is creating automatically two functions for you:
>>
>> Just :: a -> Maybe a
>> Nothing :: Maybe a
>>
>> In the first case, you can think of "Just" and "Nothing" as a sort of tag
>> identifying which element of the sum you have.
>> It the second case it's a function, with the same name.
>> A more informed person than me could say if they are indeed separated of
>> if they are the same thing in GHC...
>>
>>
>> On Thu, Mar 26, 2015 at 5:34 PM, Shishir Srivastava <
>> shishir.srivastava at gmail.com> wrote:
>>
>>> isn't that then cyclic dependency between 'Maybe' and 'Just' ...where
>>> the first one is defined in terms of second and vice-versa...?
>>>
>>> Shishir
>>>
>>>
>>> On Thu, Mar 26, 2015 at 3:48 PM, Corentin Dupont <
>>> corentin.dupont at gmail.com> wrote:
>>>
>>>> Hi Shishir,
>>>> I think that's a legitimate question.
>>>>
>>>> By writing
>>>>
>>>> data Maybe a = a | Nothing
>>>>
>>>> you are saying that the type of the left hand side of the = is the same
>>>> that right hand side (you are defining a type basically).
>>>> Also you can only sum things of the same type.
>>>> So you are saying:
>>>> type "Maybe a" = type "a"
>>>> Which is wrong.
>>>> That's why "a" should be wrapped into something:
>>>> type of "Just a" is indeed "Maybe a".
>>>>
>>>> "Just" is a type constructor:
>>>> Just :: a -> Maybe a
>>>> It allows you to build the Maybe.
>>>>
>>>> Said that, "Just" is a vocabulary choice.
>>>> Personally I prefer the name choices of OCaml, Rust, Scala etc.:
>>>> Option a = None | Some a
>>>>
>>>>
>>>>
>>>> On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
>>>> shishir.srivastava at gmail.com> wrote:
>>>>
>>>>> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
>>>>> defined like this
>>>>>
>>>>> data Maybe a = a | Nothing
>>>>>
>>>>> what's the point in having 'Just' keyword ?
>>>>>
>>>>> Shishir
>>>>>
>>>>>
>>>>> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
>>>>> mdorman at ironicdesign.com> wrote:
>>>>>
>>>>>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>>>>>> > After reading and re-reading the haskell tutorials I don't happen to
>>>>>> > see a very convincing or appealing reason for having these data
>>>>>> > types.
>>>>>>
>>>>>> To be clear: Maybe is the data *type*.  Just and Nothing are its data
>>>>>> *constructors*.
>>>>>>
>>>>>> > Can anyone please explain where Maybe and Just provide the sort of
>>>>>> > functionality that cannot be achieved in other languages which don't
>>>>>> > have these kind.
>>>>>>
>>>>>> The functionality can be achieved in other languages, certainly.  The
>>>>>> question is whether the clarity and safety is also achieved.
>>>>>>
>>>>>> When I see (as a totally contrived example):
>>>>>>
>>>>>>   fopen :: Maybe FileHandle
>>>>>>
>>>>>> I know that that function may not be able to return a FileHandle value
>>>>>> all the time.  The compiler will, in fact, nag me if I do not write
>>>>>> the
>>>>>> code that calls it in such a way that it acknowledges that
>>>>>> possibility.
>>>>>>
>>>>>> When I see:
>>>>>>
>>>>>>   FILE * fopen ( const char * filename, const char * mode );
>>>>>>
>>>>>> It is not immediately clear whether that can fail.  Sure, we can make
>>>>>> that inference, based on what we know about filesystems, etc., but the
>>>>>> compiler is never going to complain if I ignore the possibility.
>>>>>>
>>>>>> In my experience, programmers in many languages end up resorting to
>>>>>> convention to try and work around these sorts of ambiguities.  Large
>>>>>> projects have strategies for naming functions that try to pass along
>>>>>> information out of band, or languages have a pervasive culture of
>>>>>> "lint"
>>>>>> tools that try to use heuristics to make up for what the type system
>>>>>> doesn't make simple.
>>>>>>
>>>>>> That said, I know that doing Maybe sorts of things in languages that
>>>>>> don't have, say, pattern matching, or the idea of a "failure monad",
>>>>>> gets to be a drag very quickly---manually unwrapping things is at best
>>>>>> awkward, having to re-wrap them just to unwrap them again in a
>>>>>> sequence
>>>>>> of computations quickly leads one to believe "it's just not worth
>>>>>> it"---or you resort to exception handling, which has its own
>>>>>> challenges
>>>>>> to do well.
>>>>>>
>>>>>> Mike.
>>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Beginners mailing list
>>>>> Beginners at haskell.org
>>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150327/ef7134f4/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Mike Meyer
In reply to this post by Shishir Srivastava
On Fri, Mar 27, 2015 at 4:44 AM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Sorry, but I still have some grudges so to say with the way 'Maybe' is
> defined.
>
> By definition '*Maybe*' takes a type parameter which I will denote here
> as '*tp*' for the sake of clarity like below -
>
> data Maybe tp = Just tp | Nothing
>
> Therefore '*tp*' is not representing a value perse such as '3' or 'XYZ'
> etc but a data type such as '*Int*', '*Char*' etc.
>
> But when we have to create a data type of '*Maybe*' we write '*Just 3*'
> and not '*Just Int*' or '*Just Char*' which is how it's defined in the
> definition (i.e. '*Just tp*' ) .
>
> It is this discrepancy in definition and the actual value creation which
> is slightly troubling me.
>

This was already explained, all be it in passing.

Maybe Int is a type. Just and and Nothing are functions. Nothing takes no
arguments. Just takes a single argument of the type given. There IS no type
that Just Int would represent. There are only the two types Int and Maybe
Int. 3 is of type Int. Just 3 is of type Maybe Int. Nothing is of type
Maybe Int as well.

Going back to the notion of "type plus error value", Int is the type, and
Maybe Int is the type with an error value, the error value being Nothing.

It might be educational to look at a second example. Try the Either types,
which are sometimes used in a manner similar to the Maybe types. But
instead of Nothing to indicate "an error occurred", you have Left tp to
indicate that an error occurred using the value of tp to provide
information about the error.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150327/85d1b934/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Fwd: Maybe and Just

Corentin Dupont
In reply to this post by Corentin Dupont
You're right, "Just" is used at two different levels, it's just that it
have the same name is both cases.
One is at type level, the other at value level.
Since this is two separated levels, there is no risk of confusion and
having the same name is fine.

To be clear, you can write:

data Maybe = Just Int | Nothing

Then use it as:

my_value = Just 3

It the first case, "Just" is a tag in the type definition, in the second
case it's a function constructing a value.
They just happen to have the same name (a choice of Haskell language).


On Fri, Mar 27, 2015 at 10:44 AM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Sorry, but I still have some grudges so to say with the way 'Maybe' is
> defined.
>
> By definition '*Maybe*' takes a type parameter which I will denote here
> as '*tp*' for the sake of clarity like below -
>
> data Maybe tp = Just tp | Nothing
>
> Therefore '*tp*' is not representing a value perse such as '3' or 'XYZ'
> etc but a data type such as '*Int*', '*Char*' etc.
>
> But when we have to create a data type of '*Maybe*' we write '*Just 3*'
> and not '*Just Int*' or '*Just Char*' which is how it's defined in the
> definition (i.e. '*Just tp*' ) .
>
> It is this discrepancy in definition and the actual value creation which
> is slightly troubling me.
>
> Thanks,
> Shishir
>
> Shishir Srivastava
>  +44 (0) 750 127 5019
>
>
> On Thu, Mar 26, 2015 at 5:31 PM, Corentin Dupont <
> corentin.dupont at gmail.com> wrote:
>
>> Not really, when you define the type "Maybe a":
>>
>> data Maybe a = Just a | Nothing
>>
>> Haskell is creating automatically two functions for you:
>>
>> Just :: a -> Maybe a
>> Nothing :: Maybe a
>>
>> In the first case, you can think of "Just" and "Nothing" as a sort of tag
>> identifying which element of the sum you have.
>> It the second case it's a function, with the same name.
>> A more informed person than me could say if they are indeed separated of
>> if they are the same thing in GHC...
>>
>>
>> On Thu, Mar 26, 2015 at 5:34 PM, Shishir Srivastava <
>> shishir.srivastava at gmail.com> wrote:
>>
>>> isn't that then cyclic dependency between 'Maybe' and 'Just' ...where
>>> the first one is defined in terms of second and vice-versa...?
>>>
>>> Shishir
>>>
>>>
>>> On Thu, Mar 26, 2015 at 3:48 PM, Corentin Dupont <
>>> corentin.dupont at gmail.com> wrote:
>>>
>>>> Hi Shishir,
>>>> I think that's a legitimate question.
>>>>
>>>> By writing
>>>>
>>>> data Maybe a = a | Nothing
>>>>
>>>> you are saying that the type of the left hand side of the = is the same
>>>> that right hand side (you are defining a type basically).
>>>> Also you can only sum things of the same type.
>>>> So you are saying:
>>>> type "Maybe a" = type "a"
>>>> Which is wrong.
>>>> That's why "a" should be wrapped into something:
>>>> type of "Just a" is indeed "Maybe a".
>>>>
>>>> "Just" is a type constructor:
>>>> Just :: a -> Maybe a
>>>> It allows you to build the Maybe.
>>>>
>>>> Said that, "Just" is a vocabulary choice.
>>>> Personally I prefer the name choices of OCaml, Rust, Scala etc.:
>>>> Option a = None | Some a
>>>>
>>>>
>>>>
>>>> On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
>>>> shishir.srivastava at gmail.com> wrote:
>>>>
>>>>> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
>>>>> defined like this
>>>>>
>>>>> data Maybe a = a | Nothing
>>>>>
>>>>> what's the point in having 'Just' keyword ?
>>>>>
>>>>> Shishir
>>>>>
>>>>>
>>>>> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
>>>>> mdorman at ironicdesign.com> wrote:
>>>>>
>>>>>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>>>>>> > After reading and re-reading the haskell tutorials I don't happen to
>>>>>> > see a very convincing or appealing reason for having these data
>>>>>> > types.
>>>>>>
>>>>>> To be clear: Maybe is the data *type*.  Just and Nothing are its data
>>>>>> *constructors*.
>>>>>>
>>>>>> > Can anyone please explain where Maybe and Just provide the sort of
>>>>>> > functionality that cannot be achieved in other languages which don't
>>>>>> > have these kind.
>>>>>>
>>>>>> The functionality can be achieved in other languages, certainly.  The
>>>>>> question is whether the clarity and safety is also achieved.
>>>>>>
>>>>>> When I see (as a totally contrived example):
>>>>>>
>>>>>>   fopen :: Maybe FileHandle
>>>>>>
>>>>>> I know that that function may not be able to return a FileHandle value
>>>>>> all the time.  The compiler will, in fact, nag me if I do not write
>>>>>> the
>>>>>> code that calls it in such a way that it acknowledges that
>>>>>> possibility.
>>>>>>
>>>>>> When I see:
>>>>>>
>>>>>>   FILE * fopen ( const char * filename, const char * mode );
>>>>>>
>>>>>> It is not immediately clear whether that can fail.  Sure, we can make
>>>>>> that inference, based on what we know about filesystems, etc., but the
>>>>>> compiler is never going to complain if I ignore the possibility.
>>>>>>
>>>>>> In my experience, programmers in many languages end up resorting to
>>>>>> convention to try and work around these sorts of ambiguities.  Large
>>>>>> projects have strategies for naming functions that try to pass along
>>>>>> information out of band, or languages have a pervasive culture of
>>>>>> "lint"
>>>>>> tools that try to use heuristics to make up for what the type system
>>>>>> doesn't make simple.
>>>>>>
>>>>>> That said, I know that doing Maybe sorts of things in languages that
>>>>>> don't have, say, pattern matching, or the idea of a "failure monad",
>>>>>> gets to be a drag very quickly---manually unwrapping things is at best
>>>>>> awkward, having to re-wrap them just to unwrap them again in a
>>>>>> sequence
>>>>>> of computations quickly leads one to believe "it's just not worth
>>>>>> it"---or you resort to exception handling, which has its own
>>>>>> challenges
>>>>>> to do well.
>>>>>>
>>>>>> Mike.
>>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Beginners mailing list
>>>>> Beginners at haskell.org
>>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150327/767718a9/attachment-0001.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

akash g
In reply to this post by Shishir Srivastava
Think of the Maybe type as

-- Valid syntax with GADTs, I think
data Maybe a where
   Nothing :: Maybe a
   Just       :: a -> Maybe a

You are confusing types with actual values :  (Just 3) is a value with
type, (Maybe Int).

Think of it this way: A value is an object with some type and you have
Maybe value constructors via Nothing and Just.





On Fri, Mar 27, 2015 at 3:14 PM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Sorry, but I still have some grudges so to say with the way 'Maybe' is
> defined.
>
> By definition '*Maybe*' takes a type parameter which I will denote here
> as '*tp*' for the sake of clarity like below -
>
> data Maybe tp = Just tp | Nothing
>
> Therefore '*tp*' is not representing a value perse such as '3' or 'XYZ'
> etc but a data type such as '*Int*', '*Char*' etc.
>
> But when we have to create a data type of '*Maybe*' we write '*Just 3*'
> and not '*Just Int*' or '*Just Char*' which is how it's defined in the
> definition (i.e. '*Just tp*' ) .
>
> It is this discrepancy in definition and the actual value creation which
> is slightly troubling me.
>
> Thanks,
> Shishir
>
> Shishir Srivastava
>  +44 (0) 750 127 5019
>
>
> On Thu, Mar 26, 2015 at 5:31 PM, Corentin Dupont <
> corentin.dupont at gmail.com> wrote:
>
>> Not really, when you define the type "Maybe a":
>>
>> data Maybe a = Just a | Nothing
>>
>> Haskell is creating automatically two functions for you:
>>
>> Just :: a -> Maybe a
>> Nothing :: Maybe a
>>
>> In the first case, you can think of "Just" and "Nothing" as a sort of tag
>> identifying which element of the sum you have.
>> It the second case it's a function, with the same name.
>> A more informed person than me could say if they are indeed separated of
>> if they are the same thing in GHC...
>>
>>
>> On Thu, Mar 26, 2015 at 5:34 PM, Shishir Srivastava <
>> shishir.srivastava at gmail.com> wrote:
>>
>>> isn't that then cyclic dependency between 'Maybe' and 'Just' ...where
>>> the first one is defined in terms of second and vice-versa...?
>>>
>>> Shishir
>>>
>>>
>>> On Thu, Mar 26, 2015 at 3:48 PM, Corentin Dupont <
>>> corentin.dupont at gmail.com> wrote:
>>>
>>>> Hi Shishir,
>>>> I think that's a legitimate question.
>>>>
>>>> By writing
>>>>
>>>> data Maybe a = a | Nothing
>>>>
>>>> you are saying that the type of the left hand side of the = is the same
>>>> that right hand side (you are defining a type basically).
>>>> Also you can only sum things of the same type.
>>>> So you are saying:
>>>> type "Maybe a" = type "a"
>>>> Which is wrong.
>>>> That's why "a" should be wrapped into something:
>>>> type of "Just a" is indeed "Maybe a".
>>>>
>>>> "Just" is a type constructor:
>>>> Just :: a -> Maybe a
>>>> It allows you to build the Maybe.
>>>>
>>>> Said that, "Just" is a vocabulary choice.
>>>> Personally I prefer the name choices of OCaml, Rust, Scala etc.:
>>>> Option a = None | Some a
>>>>
>>>>
>>>>
>>>> On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
>>>> shishir.srivastava at gmail.com> wrote:
>>>>
>>>>> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
>>>>> defined like this
>>>>>
>>>>> data Maybe a = a | Nothing
>>>>>
>>>>> what's the point in having 'Just' keyword ?
>>>>>
>>>>> Shishir
>>>>>
>>>>>
>>>>> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
>>>>> mdorman at ironicdesign.com> wrote:
>>>>>
>>>>>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>>>>>> > After reading and re-reading the haskell tutorials I don't happen to
>>>>>> > see a very convincing or appealing reason for having these data
>>>>>> > types.
>>>>>>
>>>>>> To be clear: Maybe is the data *type*.  Just and Nothing are its data
>>>>>> *constructors*.
>>>>>>
>>>>>> > Can anyone please explain where Maybe and Just provide the sort of
>>>>>> > functionality that cannot be achieved in other languages which don't
>>>>>> > have these kind.
>>>>>>
>>>>>> The functionality can be achieved in other languages, certainly.  The
>>>>>> question is whether the clarity and safety is also achieved.
>>>>>>
>>>>>> When I see (as a totally contrived example):
>>>>>>
>>>>>>   fopen :: Maybe FileHandle
>>>>>>
>>>>>> I know that that function may not be able to return a FileHandle value
>>>>>> all the time.  The compiler will, in fact, nag me if I do not write
>>>>>> the
>>>>>> code that calls it in such a way that it acknowledges that
>>>>>> possibility.
>>>>>>
>>>>>> When I see:
>>>>>>
>>>>>>   FILE * fopen ( const char * filename, const char * mode );
>>>>>>
>>>>>> It is not immediately clear whether that can fail.  Sure, we can make
>>>>>> that inference, based on what we know about filesystems, etc., but the
>>>>>> compiler is never going to complain if I ignore the possibility.
>>>>>>
>>>>>> In my experience, programmers in many languages end up resorting to
>>>>>> convention to try and work around these sorts of ambiguities.  Large
>>>>>> projects have strategies for naming functions that try to pass along
>>>>>> information out of band, or languages have a pervasive culture of
>>>>>> "lint"
>>>>>> tools that try to use heuristics to make up for what the type system
>>>>>> doesn't make simple.
>>>>>>
>>>>>> That said, I know that doing Maybe sorts of things in languages that
>>>>>> don't have, say, pattern matching, or the idea of a "failure monad",
>>>>>> gets to be a drag very quickly---manually unwrapping things is at best
>>>>>> awkward, having to re-wrap them just to unwrap them again in a
>>>>>> sequence
>>>>>> of computations quickly leads one to believe "it's just not worth
>>>>>> it"---or you resort to exception handling, which has its own
>>>>>> challenges
>>>>>> to do well.
>>>>>>
>>>>>> Mike.
>>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Beginners mailing list
>>>>> Beginners at haskell.org
>>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>>>>
>>>>>
>>>>
>>>
>>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150327/46fd52a2/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Shishir Srivastava
In reply to this post by Corentin Dupont
Thanks Corentin. I think it makes more sense now that you've mentioned the
fact that '*Just*' in the type definition of '*Maybe*' is only a *tag*.

So would it be correct to re-define Maybe data type as follows -

data Maybe tp = Justin tp | Nothing

and then create the type value of *Maybe *as -

*Just 3*

*?*



Shishir Srivastava
 +44 (0) 750 127 5019


On Fri, Mar 27, 2015 at 10:05 AM, Corentin Dupont <corentin.dupont at gmail.com
> wrote:

>
> You're right, "Just" is used at two different levels, it's just that it
> have the same name is both cases.
> One is at type level, the other at value level.
> Since this is two separated levels, there is no risk of confusion and
> having the same name is fine.
>
> To be clear, you can write:
>
> data Maybe = Just Int | Nothing
>
> Then use it as:
>
> my_value = Just 3
>
> It the first case, "Just" is a tag in the type definition, in the second
> case it's a function constructing a value.
> They just happen to have the same name (a choice of Haskell language).
>
>
> On Fri, Mar 27, 2015 at 10:44 AM, Shishir Srivastava <
> shishir.srivastava at gmail.com> wrote:
>
>> Sorry, but I still have some grudges so to say with the way 'Maybe' is
>> defined.
>>
>> By definition '*Maybe*' takes a type parameter which I will denote here
>> as '*tp*' for the sake of clarity like below -
>>
>> data Maybe tp = Just tp | Nothing
>>
>> Therefore '*tp*' is not representing a value perse such as '3' or 'XYZ'
>> etc but a data type such as '*Int*', '*Char*' etc.
>>
>> But when we have to create a data type of '*Maybe*' we write '*Just 3*'
>> and not '*Just Int*' or '*Just Char*' which is how it's defined in the
>> definition (i.e. '*Just tp*' ) .
>>
>> It is this discrepancy in definition and the actual value creation which
>> is slightly troubling me.
>>
>> Thanks,
>> Shishir
>>
>> Shishir Srivastava
>>  +44 (0) 750 127 5019
>>
>>
>> On Thu, Mar 26, 2015 at 5:31 PM, Corentin Dupont <
>> corentin.dupont at gmail.com> wrote:
>>
>>> Not really, when you define the type "Maybe a":
>>>
>>> data Maybe a = Just a | Nothing
>>>
>>> Haskell is creating automatically two functions for you:
>>>
>>> Just :: a -> Maybe a
>>> Nothing :: Maybe a
>>>
>>> In the first case, you can think of "Just" and "Nothing" as a sort of
>>> tag identifying which element of the sum you have.
>>> It the second case it's a function, with the same name.
>>> A more informed person than me could say if they are indeed separated of
>>> if they are the same thing in GHC...
>>>
>>>
>>> On Thu, Mar 26, 2015 at 5:34 PM, Shishir Srivastava <
>>> shishir.srivastava at gmail.com> wrote:
>>>
>>>> isn't that then cyclic dependency between 'Maybe' and 'Just' ...where
>>>> the first one is defined in terms of second and vice-versa...?
>>>>
>>>> Shishir
>>>>
>>>>
>>>> On Thu, Mar 26, 2015 at 3:48 PM, Corentin Dupont <
>>>> corentin.dupont at gmail.com> wrote:
>>>>
>>>>> Hi Shishir,
>>>>> I think that's a legitimate question.
>>>>>
>>>>> By writing
>>>>>
>>>>> data Maybe a = a | Nothing
>>>>>
>>>>> you are saying that the type of the left hand side of the = is the
>>>>> same that right hand side (you are defining a type basically).
>>>>> Also you can only sum things of the same type.
>>>>> So you are saying:
>>>>> type "Maybe a" = type "a"
>>>>> Which is wrong.
>>>>> That's why "a" should be wrapped into something:
>>>>> type of "Just a" is indeed "Maybe a".
>>>>>
>>>>> "Just" is a type constructor:
>>>>> Just :: a -> Maybe a
>>>>> It allows you to build the Maybe.
>>>>>
>>>>> Said that, "Just" is a vocabulary choice.
>>>>> Personally I prefer the name choices of OCaml, Rust, Scala etc.:
>>>>> Option a = None | Some a
>>>>>
>>>>>
>>>>>
>>>>> On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
>>>>> shishir.srivastava at gmail.com> wrote:
>>>>>
>>>>>> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
>>>>>> defined like this
>>>>>>
>>>>>> data Maybe a = a | Nothing
>>>>>>
>>>>>> what's the point in having 'Just' keyword ?
>>>>>>
>>>>>> Shishir
>>>>>>
>>>>>>
>>>>>> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
>>>>>> mdorman at ironicdesign.com> wrote:
>>>>>>
>>>>>>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>>>>>>> > After reading and re-reading the haskell tutorials I don't happen
>>>>>>> to
>>>>>>> > see a very convincing or appealing reason for having these data
>>>>>>> > types.
>>>>>>>
>>>>>>> To be clear: Maybe is the data *type*.  Just and Nothing are its data
>>>>>>> *constructors*.
>>>>>>>
>>>>>>> > Can anyone please explain where Maybe and Just provide the sort of
>>>>>>> > functionality that cannot be achieved in other languages which
>>>>>>> don't
>>>>>>> > have these kind.
>>>>>>>
>>>>>>> The functionality can be achieved in other languages, certainly.  The
>>>>>>> question is whether the clarity and safety is also achieved.
>>>>>>>
>>>>>>> When I see (as a totally contrived example):
>>>>>>>
>>>>>>>   fopen :: Maybe FileHandle
>>>>>>>
>>>>>>> I know that that function may not be able to return a FileHandle
>>>>>>> value
>>>>>>> all the time.  The compiler will, in fact, nag me if I do not write
>>>>>>> the
>>>>>>> code that calls it in such a way that it acknowledges that
>>>>>>> possibility.
>>>>>>>
>>>>>>> When I see:
>>>>>>>
>>>>>>>   FILE * fopen ( const char * filename, const char * mode );
>>>>>>>
>>>>>>> It is not immediately clear whether that can fail.  Sure, we can make
>>>>>>> that inference, based on what we know about filesystems, etc., but
>>>>>>> the
>>>>>>> compiler is never going to complain if I ignore the possibility.
>>>>>>>
>>>>>>> In my experience, programmers in many languages end up resorting to
>>>>>>> convention to try and work around these sorts of ambiguities.  Large
>>>>>>> projects have strategies for naming functions that try to pass along
>>>>>>> information out of band, or languages have a pervasive culture of
>>>>>>> "lint"
>>>>>>> tools that try to use heuristics to make up for what the type system
>>>>>>> doesn't make simple.
>>>>>>>
>>>>>>> That said, I know that doing Maybe sorts of things in languages that
>>>>>>> don't have, say, pattern matching, or the idea of a "failure monad",
>>>>>>> gets to be a drag very quickly---manually unwrapping things is at
>>>>>>> best
>>>>>>> awkward, having to re-wrap them just to unwrap them again in a
>>>>>>> sequence
>>>>>>> of computations quickly leads one to believe "it's just not worth
>>>>>>> it"---or you resort to exception handling, which has its own
>>>>>>> challenges
>>>>>>> to do well.
>>>>>>>
>>>>>>> Mike.
>>>>>>>
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> Beginners mailing list
>>>>>> Beginners at haskell.org
>>>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150327/0cdff56b/attachment-0001.html>

Reply | Threaded
Open this post in threaded view
|

Maybe and Just

Joel Neely
Shishir,

Would I be right to guess that you're coming from an OO background? If so,
I'd suggest thinking about the difference between declaring a constructor
and invoking it.

I suggest that you can read the Haskell declaration

data Maybe tp = Just tp | Nothing


as declaring ?a data type and specifying two constructors that can return
an instance (in the OO sense of the word) of that data type. But when the
expression

Just "FOO"


is invoking one of those constructors on a value of type String, so the
resulting value has type Maybe String.

Because Maybe is an instance of Show (in the Haskell sense of the word),
there's a show function that can be applied to that value to produce
something that looks like the line above. That's roughly equivalent to
having a toString method on a Java class that returns a string that looks
like a constructor call that could produce the actual object.

-jn-

On Fri, Mar 27, 2015 at 5:14 AM, Shishir Srivastava <
shishir.srivastava at gmail.com> wrote:

> Thanks Corentin. I think it makes more sense now that you've mentioned the
> fact that '*Just*' in the type definition of '*Maybe*' is only a *tag*.
>
> So would it be correct to re-define Maybe data type as follows -
>
> data Maybe tp = Justin tp | Nothing
>
> and then create the type value of *Maybe *as -
>
> *Just 3*
>
> *?*
>
>
>
> Shishir Srivastava
>  +44 (0) 750 127 5019
>
>
> On Fri, Mar 27, 2015 at 10:05 AM, Corentin Dupont <
> corentin.dupont at gmail.com> wrote:
>
>>
>> You're right, "Just" is used at two different levels, it's just that it
>> have the same name is both cases.
>> One is at type level, the other at value level.
>> Since this is two separated levels, there is no risk of confusion and
>> having the same name is fine.
>>
>> To be clear, you can write:
>>
>> data Maybe = Just Int | Nothing
>>
>> Then use it as:
>>
>> my_value = Just 3
>>
>> It the first case, "Just" is a tag in the type definition, in the second
>> case it's a function constructing a value.
>> They just happen to have the same name (a choice of Haskell language).
>>
>>
>> On Fri, Mar 27, 2015 at 10:44 AM, Shishir Srivastava <
>> shishir.srivastava at gmail.com> wrote:
>>
>>> Sorry, but I still have some grudges so to say with the way 'Maybe' is
>>> defined.
>>>
>>> By definition '*Maybe*' takes a type parameter which I will denote here
>>> as '*tp*' for the sake of clarity like below -
>>>
>>> data Maybe tp = Just tp | Nothing
>>>
>>> Therefore '*tp*' is not representing a value perse such as '3' or 'XYZ'
>>> etc but a data type such as '*Int*', '*Char*' etc.
>>>
>>> But when we have to create a data type of '*Maybe*' we write '*Just 3*'
>>> and not '*Just Int*' or '*Just Char*' which is how it's defined in the
>>> definition (i.e. '*Just tp*' ) .
>>>
>>> It is this discrepancy in definition and the actual value creation which
>>> is slightly troubling me.
>>>
>>> Thanks,
>>> Shishir
>>>
>>> Shishir Srivastava
>>>  +44 (0) 750 127 5019
>>>
>>>
>>> On Thu, Mar 26, 2015 at 5:31 PM, Corentin Dupont <
>>> corentin.dupont at gmail.com> wrote:
>>>
>>>> Not really, when you define the type "Maybe a":
>>>>
>>>> data Maybe a = Just a | Nothing
>>>>
>>>> Haskell is creating automatically two functions for you:
>>>>
>>>> Just :: a -> Maybe a
>>>> Nothing :: Maybe a
>>>>
>>>> In the first case, you can think of "Just" and "Nothing" as a sort of
>>>> tag identifying which element of the sum you have.
>>>> It the second case it's a function, with the same name.
>>>> A more informed person than me could say if they are indeed separated
>>>> of if they are the same thing in GHC...
>>>>
>>>>
>>>> On Thu, Mar 26, 2015 at 5:34 PM, Shishir Srivastava <
>>>> shishir.srivastava at gmail.com> wrote:
>>>>
>>>>> isn't that then cyclic dependency between 'Maybe' and 'Just' ...where
>>>>> the first one is defined in terms of second and vice-versa...?
>>>>>
>>>>> Shishir
>>>>>
>>>>>
>>>>> On Thu, Mar 26, 2015 at 3:48 PM, Corentin Dupont <
>>>>> corentin.dupont at gmail.com> wrote:
>>>>>
>>>>>> Hi Shishir,
>>>>>> I think that's a legitimate question.
>>>>>>
>>>>>> By writing
>>>>>>
>>>>>> data Maybe a = a | Nothing
>>>>>>
>>>>>> you are saying that the type of the left hand side of the = is the
>>>>>> same that right hand side (you are defining a type basically).
>>>>>> Also you can only sum things of the same type.
>>>>>> So you are saying:
>>>>>> type "Maybe a" = type "a"
>>>>>> Which is wrong.
>>>>>> That's why "a" should be wrapped into something:
>>>>>> type of "Just a" is indeed "Maybe a".
>>>>>>
>>>>>> "Just" is a type constructor:
>>>>>> Just :: a -> Maybe a
>>>>>> It allows you to build the Maybe.
>>>>>>
>>>>>> Said that, "Just" is a vocabulary choice.
>>>>>> Personally I prefer the name choices of OCaml, Rust, Scala etc.:
>>>>>> Option a = None | Some a
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Thu, Mar 26, 2015 at 4:26 PM, Shishir Srivastava <
>>>>>> shishir.srivastava at gmail.com> wrote:
>>>>>>
>>>>>>> ok..but what's with using the keyword 'Just' ? why cannot 'Maybe' be
>>>>>>> defined like this
>>>>>>>
>>>>>>> data Maybe a = a | Nothing
>>>>>>>
>>>>>>> what's the point in having 'Just' keyword ?
>>>>>>>
>>>>>>> Shishir
>>>>>>>
>>>>>>>
>>>>>>> On Thu, Mar 26, 2015 at 10:26 AM, Michael Alan Dorman <
>>>>>>> mdorman at ironicdesign.com> wrote:
>>>>>>>
>>>>>>>> Shishir Srivastava <shishir.srivastava at gmail.com> writes:
>>>>>>>> > After reading and re-reading the haskell tutorials I don't happen
>>>>>>>> to
>>>>>>>> > see a very convincing or appealing reason for having these data
>>>>>>>> > types.
>>>>>>>>
>>>>>>>> To be clear: Maybe is the data *type*.  Just and Nothing are its
>>>>>>>> data
>>>>>>>> *constructors*.
>>>>>>>>
>>>>>>>> > Can anyone please explain where Maybe and Just provide the sort of
>>>>>>>> > functionality that cannot be achieved in other languages which
>>>>>>>> don't
>>>>>>>> > have these kind.
>>>>>>>>
>>>>>>>> The functionality can be achieved in other languages, certainly.
>>>>>>>> The
>>>>>>>> question is whether the clarity and safety is also achieved.
>>>>>>>>
>>>>>>>> When I see (as a totally contrived example):
>>>>>>>>
>>>>>>>>   fopen :: Maybe FileHandle
>>>>>>>>
>>>>>>>> I know that that function may not be able to return a FileHandle
>>>>>>>> value
>>>>>>>> all the time.  The compiler will, in fact, nag me if I do not write
>>>>>>>> the
>>>>>>>> code that calls it in such a way that it acknowledges that
>>>>>>>> possibility.
>>>>>>>>
>>>>>>>> When I see:
>>>>>>>>
>>>>>>>>   FILE * fopen ( const char * filename, const char * mode );
>>>>>>>>
>>>>>>>> It is not immediately clear whether that can fail.  Sure, we can
>>>>>>>> make
>>>>>>>> that inference, based on what we know about filesystems, etc., but
>>>>>>>> the
>>>>>>>> compiler is never going to complain if I ignore the possibility.
>>>>>>>>
>>>>>>>> In my experience, programmers in many languages end up resorting to
>>>>>>>> convention to try and work around these sorts of ambiguities.  Large
>>>>>>>> projects have strategies for naming functions that try to pass along
>>>>>>>> information out of band, or languages have a pervasive culture of
>>>>>>>> "lint"
>>>>>>>> tools that try to use heuristics to make up for what the type system
>>>>>>>> doesn't make simple.
>>>>>>>>
>>>>>>>> That said, I know that doing Maybe sorts of things in languages that
>>>>>>>> don't have, say, pattern matching, or the idea of a "failure monad",
>>>>>>>> gets to be a drag very quickly---manually unwrapping things is at
>>>>>>>> best
>>>>>>>> awkward, having to re-wrap them just to unwrap them again in a
>>>>>>>> sequence
>>>>>>>> of computations quickly leads one to believe "it's just not worth
>>>>>>>> it"---or you resort to exception handling, which has its own
>>>>>>>> challenges
>>>>>>>> to do well.
>>>>>>>>
>>>>>>>> Mike.
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> Beginners mailing list
>>>>>>> Beginners at haskell.org
>>>>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>


--
Beauty of style and harmony and grace and good rhythm depend on simplicity.
- Plato
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150327/04700875/attachment-0001.html>

12