package scotch.data.fractional;
import static java.util.Arrays.asList;
import static scotch.runtime.RuntimeSupport.applicable;
import static scotch.runtime.RuntimeSupport.flatCallable;
import static scotch.symbol.Value.Fixity.LEFT_INFIX;
import static scotch.symbol.type.TypeDescriptors.fn;
import static scotch.symbol.type.TypeDescriptors.sum;
import static scotch.symbol.type.TypeDescriptors.var;
import scotch.data.int_.Int;
import scotch.data.num.Num;
import scotch.data.ratio.Ratio;
import scotch.runtime.Applicable;
import scotch.runtime.Callable;
import scotch.symbol.TypeClass;
import scotch.symbol.TypeParameter;
import scotch.symbol.Value;
import scotch.symbol.ValueType;
import scotch.symbol.type.TypeDescriptor;
@SuppressWarnings("unused")
@TypeClass(memberName = "Fractional", parameters = {
@TypeParameter(name = "a", constraints = "scotch.data.num.Num"),
})
public interface Fractional<A> {
TypeDescriptor a = var("a", asList("scotch.data.fractional.Fractional", "scotch.data.num.Num"));
@Value(memberName = "/", fixity = LEFT_INFIX, precedence = 7)
static <A> Applicable<Fractional<A>, Applicable<Num<A>, Applicable<A, Applicable<A, A>>>> divide() {
return applicable(fractional -> applicable(num -> applicable(left -> applicable(right -> flatCallable(() -> fractional.call().divide(num, left, right))))));
}
@ValueType(forMember = "/")
static TypeDescriptor divide$type() {
return fn(a, fn(a, a));
}
@Value(memberName = "fromRatio")
static <A> Applicable<Fractional<A>, Applicable<Num<A>, Applicable<Ratio<Integer>, A>>> fromRatio() {
return applicable(fractional -> applicable(num -> applicable(ratio -> flatCallable(() -> fractional.call().fromRatio(num, ratio)))));
}
@ValueType(forMember = "fromRatio")
static TypeDescriptor fromRatio$type() {
return fn(sum("scotch.data.ratio.Ratio", asList(Int.TYPE)), a);
}
@Value(memberName = "reciprocal")
static <A> Applicable<Fractional<A>, Applicable<Num<A>, Applicable<A, A>>> reciprocal() {
return applicable(fractional -> applicable(num -> applicable(operand -> flatCallable(() -> fractional.call().reciprocal(num, operand)))));
}
@ValueType(forMember = "reciprocal")
static TypeDescriptor reciprocal$type() {
return fn(a, a);
}
Callable<A> divide(Callable<Num<A>> num, Callable<A> left, Callable<A> right);
Callable<A> fromRatio(Callable<Num<A>> num, Callable<Ratio<Integer>> ratio);
Callable<A> reciprocal(Callable<Num<A>> num, Callable<A> operand);
}