ich durch „Haskell Programmierung von ersten Prinzipien“ werde und ich fand ich in der folgenden Art und Weise des Schreiben von Code über und über:Abstracting HSPEC testet
type IntToInt = Fun Int Int
type TypeIdentity = ConcreteFunctorType Int -> Bool
type TypeComposition = ConcreteFunctorType Int -> IntToInt -> IntToInt -> Bool
checkSomething :: IO()
checkSomething = hspec $ do
describe "Some functor" $ do
it "identity property" $ do
property $ (functorIdentity :: TypeIdentity)
it "composition property" $ do
property $ (functorComposition :: TypeComposition)
ich schon versucht, diese zu abstrahieren, aber auf meiner Ebene Ich bin nicht in der Lage
checkFunctor :: (Functor f) => String -> f a -> IO()
checkFunctor description f = hspec $ do
describe description $ do
it "identity property" $ do
property $ (functorIdentity :: f a -> TypeIdentity)
it "composition property" $ do
property $ (functorComposition :: f a -> TypeComposition)
EDIT Abbildung einen Ausweg, um es
funktioniertwas würde ich wie dieser
war etwas erreichen gern zu: nach Sapan oia Antwort habe ich versucht, wie folgttype TypeIdentity = Bool
type TypeComposition = Fun Int Int -> Fun Int Int -> Bool
checkFunctor :: forall f a. (Functor f) => String -> f a -> IO()
checkFunctor description f = hspec $ do
describe description $ do
it "identity property" $ do
property $ (functorIdentity :: f a -> TypeIdentity)
it "composition property" $ do
property $ (functorCompose' :: f a -> TypeComposition)
aber ich bekomme die folgende Fehler
FunctorCheck.hs:22:25: error:
• Couldn't match type ‘a’ with ‘Int’
‘a’ is a rigid type variable bound by
the type signature for:
checkFunctor :: forall (f :: * -> *) a.
Functor f =>
String -> f a -> IO()
at FunctorCheck.hs:16:26
Expected type: f a -> TypeComposition
Actual type: f Int -> Fun Int Int -> Fun Int Int -> Bool
Es wird dann ziemlich kompliziert für mich die Typen zu definieren, die beliebige Werte und Funktionen zu erzeugen.
Gibt es eine Möglichkeit ich die Art von checkFunctor auf einen bestimmten Typ wie die folgende binden kann?
checkFuntor :: checkFunctor :: forall f Int. (Functor f) => String -> f a -> IO()
natürlich habe ich versucht, diese und es gibt mir einen Parser-Fehler, nehme ich es nur mich nicht mit ‚forall‘ richtig.
Ja, ist es möglich. Sie können dies tun 'ScopedTypeVariables' verwenden, und es kann mit GHC 8 der' TypeApplications' zusammen mit 'AllowAmbiguousTypes' noch schöner gemacht werden. –
'forall' wird verwendet, um einen neuen Typ * variable * einzuführen. * Beton * -Typen wie "Int" müssen nicht eingeführt werden, sondern nur anstelle einer * -Typ-Variable *. Ihr Beispiel wird dann: 'checkFunctor :: forall f. (Functor f) => Zeichenkette -> f Int -> IO() '. Im Körper von 'checkFunctor' müssen Sie entsprechend:' functorIdentity :: f Int -> TypeIdentity'. – sapanoia