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 <shishir.srivastava@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@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners