Difficulties with std.variant.Algebraic

Meta jared771 at gmail.com
Wed Jul 10 20:06:30 PDT 2013


I've been playing around with std.variant.Algebraic, trying to 
define a very simple option type. However, I've been running into 
quite a few problems. My implementation is as follows:

import std.conv;
import std.variant;

struct Some(T)
{
     T payload;

     alias payload this;
}

struct None
{
}

struct Option(T)
{	
     Algebraic!(Some!T, None) payload;

     alias payload this;
}

Option!int unreliable(int val)
{
     if (val == 0)
     {
         return None();
     }
     else
     {
         return Some!int(val);
     }
}


Unfortunately, I can't return values of type Some or None from 
"unreliable" and expect the compiler to know that they should 
become an Algebraic wrapped in an Option. This is annoying, but I 
can't expect magic. Maybe if I'm explicit:

Option!int unreliable(int val)
{
     if (val == 0)
     {
         //Nope
	return cast(Option!int)None();
     }
     else
     {
         //Nope
	return cast(Option!int)Some!int(val);
     }
}

Option!int unreliable(int val)
{
     if (val == 0)
     {
         //Nope
	return cast(Option!int)None();
     }
     else
     {
         //Nope
	return cast(Option!int)Some!int(val);
     }
}

Option!int unreliable(int val)
{
     if (val == 0)
     {
         //Nope
	return cast(Algebraic!(Some!int, None))None();
     }
     else
     {
         //Nope
	return cast(Algebraic!(Some!int, None))Some!int(val);
     }
}


Okay, I'll try constructing a fresh struct and returning that:

Option!int unreliable(int val)
{
     if (val == 0)
     {
         //Nope
	return Option!int(None());
     }
     else
     {
         //Nope
	return Option!int(Some!int(val));
     }
}


One final, last-ditch effort:

Option!int unreliable(int val)
{
     if (val == 0)
     {
         return Option!int(cast(Algebraic!(Some!int, None))None());
     }
     else
     {
         return Option!int(cast(Algebraic!(Some!int, 
None))Some!int(val));
     }
}


Yes! It worked. The only problem is that this is completely 
unacceptable to type. The only other solution I can think of 
would be to define constructors for Option that take a Some and a 
None. I suppose it's not *all* bad, though. I mean, it compiles...

void main()
{
     auto maybeNone = unreliable(10);
     //Error: template std.variant.visit cannot deduce template 
function from argument types !()(Option!(int))
     assert(maybeNone.visit!((Some!int s) => text("Value is ", s),
                             (None n) => "No value")
                     == 10);
}


I don't know whether to laugh or cry.


More information about the Digitalmars-d-learn mailing list