をテストSapan後 :それは私が達成したかった何抽象化Hspecは、私は、「第一原理からのHaskellプログラミング」を経由していると私は自分自身が何度も次の方法でコードを書いた
を動作させるための方法を把握するために、この
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のようなものでした
type 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)
を次のようにイアの答えは、私が試したが、私は次のエラーを取得する
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
私は任意の値と関数を生成するために型を定義することは、その後かなり複雑になります。
checkFunctorのタイプを次のような特定のタイプにバインドする方法はありますか?当然の
checkFuntor :: checkFunctor :: forall f Int. (Functor f) => String -> f a -> IO()
私はこれを試してみましたが、それは私のパースエラーを与え、私はそれがちょうど私が正しく「FORALL」を使用していないと仮定します。
はい、可能です。 'ScopedTypeVariables'を使ってこれを行うことができます.GHC 8の' TypeApplications'と 'AllowAmbiguousTypes'を使ってより良いものにすることができます。 –
'forall'は新しい型*変数*を導入するために使われます。 * 'Int'のような具象型は導入する必要はなく、型変数*の代わりに挿入するだけです。あなたの例は次のようになります: 'checkFunctor :: forall f。 (Functor f)=>文字列 - > f Int - > IO() ' 'checkFunctor'の本体には、それに応じて' functorIdentity :: f Int - > TypeIdentity'が必要です。 – sapanoia