首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >抽象Hspec试验

抽象Hspec试验
EN

Stack Overflow用户
提问于 2016-12-07 23:57:31
回答 1查看 92关注 0票数 1

我正在学习"Haskell programming from first principles“,我发现自己一遍又一遍地用以下方式编写代码:

代码语言:javascript
复制
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)

我试着把它抽象出来,但在我的层次上,我无法想出一种方法来使它工作。

我想要实现的是这样的

代码语言:javascript
复制
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)

编辑:萨帕诺亚回答后,我试了如下

代码语言:javascript
复制
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)

但是我得到了以下错误

代码语言:javascript
复制
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类型绑定到特定类型,如以下所示?

代码语言:javascript
复制
checkFuntor :: checkFunctor :: forall f Int. (Functor f) => String -> f a -> IO ()

当然,我尝试过这一点,它给了我一个解析错误,我想只是我没有正确地使用“forall”。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-08 00:08:13

由于您没有添加错误消息,我假设问题是定义了(functorIdentity :: f a -> TypeIdentity)的类型错误。问题是这里引入的f是新的,与顶级签名中的f不同。若要纠正此情况,请启用以下扩展:

代码语言:javascript
复制
{-# LANGUAGE ScopedTypeVariables #-}

并将checkFunctor的签名更改为:

代码语言:javascript
复制
checkFunctor :: forall f a. (Functor f) => String -> f a -> IO ()

forall引入了新的类型变量。没有ScopedTypeVariables和显式forall,它总是隐式地存在,而(functorIdentity :: f a -> TypeIdentity)变成了(functorIdentity :: forall f a. f a -> TypeIdentity)。但是,您在这里不需要所有的变量,因为您希望类型变量fa与顶级变量相同。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41029511

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档