As you have it coded, $slope is a Formula, and $slopeeval is the result of evaluating $slope at ($x,$y). Calling eval will always result in the final computation, meaning that no operations will be preserved. So $slopeeval being defined in this way will never be a fraction.
You're also going to need to turn off the reduceConstants context flag to avoid turning fractions into decimals:
Context()->flags->set(reduceConstants=>0);
Now, unless you are going to use $dx and $dy in a displayed solution, you don't need to call reduce after taking the derivative. You're more interested here in their value at ($x,$y), so replace the "reduce" call with -> eval(x=>$x, y=>$y).
$f = Formula("x**2+3*y**3");
$y = 1;
$x = 1;
$dx = $f -> D('x') -> eval(x => $x, y => $y);
$dy = $f -> D('y') -> eval(x => $x, y => $y);
This will get you the numerator and denominator of your slope, so you can set:
$ans = ImplicitEquation("y-$y=-($dx/$dy)*(x-$x)");
However, if you're looking to randomize this problem (or change $f), you're going to run into some more problems.
Here's my suggestion for randomizing this problem. It should allow you to code up as many variants as you like by simply changing the definition of $f.
DOCUMENT();
loadMacros(
"PGstandard.pl",
"PGML.pl",
"PGcourse.pl",
"MathObjects.pl",
"parserImplicitEquation.pl",
);
TEXT(beginproblem());
Context("ImplicitEquation");
Context()->flags->set(reduceConstants=>0); # Preserve constant formulas
Context()->variables->set(x=>{limits=>[-5,5]}, y=>{limits=>[-5,5]});
$f = Formula("x**2+3*y**3");
$y = random(-5,5,1);
$x = random(-5,5,1);
$result = $f -> eval(x=>$x, y=>$y); # so that our random point lies on $f = $result
$dx = $f -> D('x') -> eval(x=>$x, y=>$y);
$dy = $f -> D('y') -> eval(x=>$x, y=>$y);
# manually reduce the slope fraction #
##############################
$gcf = gcf(abs($dx),abs($dy));
$dx = Real("$dx/$gcf");
$dy = Real("$dy/$gcf");
if ( ($dx < 0 && $dy < 0) || ($dx > 0 && $dy > 0) ) {
$m = Formula("-(abs($dx)/abs($dy))");
} else {
$m = Formula("abs($dx)/abs($dy)");
};
# reduce potential subtraction of negatives in our solution #
###############################################
$lhs = Formula("y-$y")->reduce;
$rhs = Formula("x-$x")->reduce;
# throw in the slope AFTER calling reduce, to preserve the fraction #
######################################################
$rhs = Compute("$m*$rhs");
$ans = ImplicitEquation("$lhs=$rhs");
BEGIN_PGML
Find the line that is tangent to the graph of the equation [`` [$f] = [$result] ``] at the point [`` ([$x],[$y]) ``].
[_____________________________]{$ans}.
END_PGML
ENDDOCUMENT();