
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="<