I have the following code, which does not compile:
import Numeric.AD
data Trainable a b = forall n . Floating n => Trainable ([n] -> a -> b) (a -> b -> [n] -> n)
trainSgdFull :: (Floating n, Ord n) => Trainable a b -> [n] -> a -> b -> [[n]]
trainSgdFull (Trainable _ cost) init input target = gradientDescent (cost input target) init
I want to use the Trainable type to represent machine learning systems trainable by gradient descent. The first arguemnt would be the transfer function, and the sencond would be the cost function, a is the input type, and b is the output/target type, and the list contains the learnable parameters.
The compiler complains this:
src/MachineLearning/Training.hs:12:73:
Could not deduce (n1 ~ ad-3.3.1.1:Numeric.AD.Internal.Types.AD s n)
from the context (Floating n, Ord n)
bound by the type signature for
trainSgdFull :: (Floating n, Ord n) =>
Trainable a b -> [n] -> a -> b -> [[n]]
at src/MachineLearning/Training.hs:12:3-95
or from (Floating n1)
bound by a pattern with constructor
Trainable :: forall a b n.
Floating n =>
([n] -> a -> b) -> (a -> b -> [n] -> n) -> Trainable a b,
in an equation for `trainSgdFull'
at src/MachineLearning/Training.hs:12:17-32
or from (Numeric.AD.Internal.Classes.Mode s)
bound by a type expected by the context:
Numeric.AD.Internal.Classes.Mode s =>
[ad-3.3.1.1:Numeric.AD.Internal.Types.AD s n]
-> ad-3.3.1.1:Numeric.AD.Internal.Types.AD s n
at src/MachineLearning/Training.hs:12:56-95
`n1' is a rigid type variable bound by
a pattern with constructor
Trainable :: forall a b n.
Floating n =>
([n] -> a -> b) -> (a -> b -> [n] -> n) -> Trainable a b,
in an equation for `trainSgdFull'
at src/MachineLearning/Training.hs:12:17
Expected type: [ad-3.3.1.1:Numeric.AD.Internal.Types.AD s n1]
-> ad-3.3.1.1:Numeric.AD.Internal.Types.AD s n1
Actual type: [n] -> n
In the return type of a call of `cost'
In the first argument of `gradientDescent', namely
`(cost input target)'
Is the basic concept right? If it is, how could I make the code compile?
The problem is that
means that in
the type
nused is lost. All that is known is that there is some typeGuessmewith aFloatinginstance such thatYou can build
Trainables with functions that only work forComplex Float, or only forDouble, or …But in
you are trying to use
costwith whateverFloatingtype is supplied as an argument.The
Trainablewas built to work with typen0, the user supplies typen1, and those may or may not be the same. Thus the compiler can’t deduce they are the same.If you don’t want to make
na type parameter ofTrainable, you need to make it wrap polymorphic functions that work with everyFloatingtype the caller supplies(needs
Rank2Types, or, since that is in the process of being deprecated,RankNTypes).