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); }