首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不合法的多态型或合格型

不合法的多态型或合格型
EN

Stack Overflow用户
提问于 2015-07-20 18:36:58
回答 1查看 245关注 0票数 2

我正在尝试扩展(或试图找出是否有可能扩展)一个类型签名的函数,该类型签名已经达到了我的知识范围,因为我使用的库将非常多态的类型和API公开给更多的多态类型和API。

我使用的是persistenthsqml,这两个库都有非常丰富的类型,至少对我来说是这样。

我需要将persistent实体包装到hsqml“代理”对象中,以便公开给QML (基本上是javascript)。为此,我让自己成为一个名为getStandardClassMembers的帮手。你就这样用它:

代码语言:javascript
复制
instance DefaultClass (Entity Project) where
    classMembers = getStandardClassMembers
        [
            ("name", projectName),
            ("hasCustomIcon", text . not . BS.null . projectIcon),
            ("hasDev", projectHasDev), -- TODO bool as string, ugly..
            ("hasUat", projectHasUat),
            ("hasStaging", projectHasStage),
            ("hasProd", projectHasProd)
        ]
        []

getStandardClassMembers的定义是那里。它用我指定的成员定义一个javascript对象,并调用我给出的haskell函数来实现JS对象的成员。

这很不错,但是有一个“但是”。对中第二个位置的函数必须返回Text。在这里,除了第一个函数之外,我更愿意返回一个Bool。因此,理想情况下,我会使getStandardClassMembers的类型签名更加多态,而不需要第二个函数返回一个Text。再说一次,我不知道是否可能,但我决定试一试。

因此,我将RankNTypes添加到该文件的大量语言扩展名列表中(由于我选择的库,这些库都很棒),我被迫加入其中。

我改变了:

代码语言:javascript
复制
getStandardClassMembers :: (Marshal tr, ToBackendKey SqlBackend record, Typeable record,
     MarshalMode tr ICanReturnTo () ~ Yes) =>
    [(String, record -> tr)] -> [(String, ObjRef (Entity record) -> Maybe Int)]
    -> [Member (GetObjType (ObjRef (Entity record)))]

至:

代码语言:javascript
复制
getStandardClassMembers :: (Marshal tr, ToBackendKey SqlBackend record, Typeable record,
     MarshalMode tr ICanReturnTo () ~ Yes) =>
    [(String, forall tr. record -> tr)] -> [(String, ObjRef (Entity record) -> Maybe Int)]
    -> [Member (GetObjType (ObjRef (Entity record)))]

(所以我添加了forall tr.),我得到了:

代码语言:javascript
复制
Illegal polymorphic or qualified type: forall tr. record -> tr
Perhaps you intended to use ImpredicativeTypes

现在,我对这些事情有了足够的了解,知道启用ImpredicativeTypes不是一个好主意。另外,如果我启用它,它也不起作用。

我想要的是可以实现的,还是应该让它休息一下,并感谢那些已经非常混乱的类型签名和语言扩展集合,任何事情都能奏效呢?

编辑--也许正确的解决方法是忘记我的助手,并使用hsqml basic API返回到基础知识。但除此之外,我仍然很好奇这是否可能。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-20 23:09:30

我认为最基本的问题是,您试图将不同类型的值放在一个列表中。即使是ImpredicativeTypes,也不允许您以所需的方式进行此操作。存在主义类型可以使用包装器,但我认为它们也太过分了。

相反,我建议从插入元组改为插入始终是相同类型的东西,这取决于您实际如何使用元组。看看你的链接代码

代码语言:javascript
复制
\(name, f) -> defPropertyConst name (return . f . entityVal . fromObjRef)

作为您在元组上使用的函数,可以从元组中获得实际需要的内容。那么,为什么不为此定义一个全局函数呢?

代码语言:javascript
复制
stdMember name f = defPropertyConst name (return . f . entityVal . fromObjRef)

(这个名称只是一个建议;您可能需要更短的东西,甚至是一个操作符。)

然后将getStandardClassMembers更改为将此类值的列表作为其第一个参数,而对于第二个参数则可能类似。

假设没有更多的类型微妙之处,那么您应该能够编写

代码语言:javascript
复制
instance DefaultClass (Entity Project) where
    classMembers = getStandardClassMembers
        [
            stdMember "name" projectName,
            stdMember "hasCustomIcon" $ text . not . BS.null . projectIcon,
            stdMember "hasDev" projectHasDev, -- TODO bool as string, ugly..
            stdMember "hasUat" projectHasUat,
            stdMember "hasStaging" projectHasStage,
            stdMember "hasProd" projectHasProd
        ]
        []
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31523905

复制
相关文章

相似问题

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