Re: [Haskell-beginners] Maybe and Just

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@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@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@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@ironicdesign.com> wrote:
Shishir Srivastava
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@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

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
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@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@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@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@ironicdesign.com> wrote:
Shishir Srivastava
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@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

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@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@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@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@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@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@ironicdesign.com> wrote:
Shishir Srivastava
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@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

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@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@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@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@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@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@ironicdesign.com> wrote:
Shishir Srivastava
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@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

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 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@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@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@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@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@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@ironicdesign.com> wrote: > Shishir Srivastava _______________________________________________
Beginners mailing list
Beginners@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

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@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@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@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@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@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@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@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@ironicdesign.com> wrote: > >> Shishir Srivastava
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@haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > _______________________________________________ Beginners mailing list Beginners@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

On 03/27/2015 02:01 PM, Joel Neely wrote:
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.
[snip]
Or, Maybe can be thought of as an abstract class with concrete
subclasses, Just and Nothing.
Or, Maybe can be thought of like a tagged union. In c++ syntax:
enum MaybeTag{ JustTag, NothingTag};
template<typename ValType>
struct JustType
{
ValType my_val;
JustType(ValType a_val)
: my_val(a_val)
{}
};
struct NothingType
{};
template<typename ValType>
struct Maybe
{
private:
MaybeTag
my_tag;
union possible_values
{ JustType<ValType> just_val;
NothingType nothing_val;
possible_values(ValType a_val)
: just_val(a_val)
{}
possible_values()
: nothing_val()
{}
}
my_val;
Maybe(ValType a_val)
: my_tag(JustTag)
, my_val(a_val)
{
}
Maybe()
: my_tag(NothingTag)
, my_val()
{}
public:
MaybeTag
tag()const
{ return my_tag;
}
static Maybe<ValType>
Just(ValType a_val)
{ return Maybe<ValType>(a_val);
}
static Maybe<ValType>
Nothing()
{ return Maybe<ValType>();
}
};
#include <iostream>
int main()
{
auto mj=Maybe<int>::Just(5);
std::cout<<"mj.tag="<

On Fri, Mar 27, 2015 at 4:44 AM, Shishir Srivastava < shishir.srivastava@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.

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@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@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@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@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@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@ironicdesign.com> wrote:
Shishir Srivastava
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@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (6)
-
akash g
-
Corentin Dupont
-
Joel Neely
-
Larry Evans
-
Mike Meyer
-
Shishir Srivastava