我正在学习"Haskell programming from first principles“,我发现自己一遍又一遍地用以下方式编写代码:
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)我试着把它抽象出来,但在我的层次上,我无法想出一种方法来使它工作。
我想要实现的是这样的
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)编辑:萨帕诺亚回答后,我试了如下
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”。
发布于 2016-12-08 00:08:13
由于您没有添加错误消息,我假设问题是定义了(functorIdentity :: f a -> TypeIdentity)的类型错误。问题是这里引入的f是新的,与顶级签名中的f不同。若要纠正此情况,请启用以下扩展:
{-# LANGUAGE ScopedTypeVariables #-}并将checkFunctor的签名更改为:
checkFunctor :: forall f a. (Functor f) => String -> f a -> IO ()forall引入了新的类型变量。没有ScopedTypeVariables和显式forall,它总是隐式地存在,而(functorIdentity :: f a -> TypeIdentity)变成了(functorIdentity :: forall f a. f a -> TypeIdentity)。但是,您在这里不需要所有的变量,因为您希望类型变量f和a与顶级变量相同。
https://stackoverflow.com/questions/41029511
复制相似问题