当前位置: 首页 > 知识库问答 >
问题:

带有Haskell约束的不安全蕴含

卫嘉泽
2023-03-14

我正在使用约束包(用于GHC Haskell)。我有一个类型族,用于确定类型级别列表是否包含一个元素:

type family HasElem (x :: k) (xs :: [k]) where
  HasElem x '[] = False                                                                               
  HasElem x (x ': xs) = True                                                                          
  HasElem x (y ': xs) = HasElem x xs

这很有效,但有一件事它没有给我的知识是

HasElem x xs   entails   HasElem x (y ': xs)

因为类型族不是“is element of”语句的归纳定义(就像在agda中一样)。我很确定,在GADT可升级到类型级别之前,无法用数据类型表示列表成员身份。

所以,我使用了约束包来编写这个:

containerEntailsLarger :: Proxy x -> Proxy xs -> Proxy b -> (HasElem x xs ~ True) :- (HasElem x (b ': xs) ~ True)
containerEntailsLarger _ _ _ = unsafeCoerceConstraint

怪异,但它的工作。我可以在蕴含物上进行图案匹配来得到我需要的东西。我想知道的是它是否会导致程序崩溃。它似乎不能,因为un安全CoerceConstraint定义为:

unsafeCoerceConstraint = unsafeCoerce refl

在GHC中,类型级别在运行时被省略。我想我应该检查一下,确保这样做没问题。

#编辑

由于还没有人给出解释,我想我应该把这个问题扩大一点。在我创造的不安全的环境中,我只期待一个类型的家庭。如果我做了一些涉及打字字典的事情,而不是像这样:

badEntailment :: Proxy a -> (Show a) :- (Ord a)
badEntailment _ = unsafeCoerceConstraint

我认为这几乎肯定会导致SEG故障。这是真的吗?如果是的话,是什么让它与原来的不同呢?

---编辑2---

我只是想提供一点背景知识来解释我为什么对这个感兴趣。我的兴趣之一是在Haskell中对关系代数进行可用的编码。我认为,无论您如何定义函数来处理类型级列表,都会有一些明显的事情没有得到正确的证明。例如,我之前遇到的一个约束(对于半连接)看起来像这样(这是来自内存,所以可能不准确):

semijoin :: ( GetOverlap as bs ~ Overlap inAs inBoth inBs
            , HasElem x as, HasElem x (inAs ++ inBoth ++ inBs)) => ...

所以,(对一个人来说)很明显,如果我取两个集合的并集,它包含一个元素x,这个元素中是,但我不确定约束求解者是否有可能合法地说服这一点。这就是我玩这个把戏的动机。我创建包含来欺骗约束求解器,但我不知道它是否真的安全。


共有1个答案

严瑞
2023-03-14

我不知道这是否适合你的其他需要,但它实现了这个特殊的目的。我自己对类型家族不太在行,所以我不清楚你的类型家族到底可以用来做什么。

{-# LANGUAGE ...., UndecidableInstances #-}
type family Or (x :: Bool) (y :: Bool) :: Bool where
  Or 'True x = 'True
  Or x 'True = 'True
  Or x y = 'False

type family Is (x :: k) (y :: k) where
  Is x x = 'True
  Is x y = 'False

type family HasElem (x :: k) (xs :: [k]) :: Bool where
  HasElem x '[] = 'False
  HasElem x (y ': z) = Or (Is x y) (HasElem x z)

containerEntailsLarger :: proxy1 x -> proxy2 xs -> proxy3 b ->
                          (HasElem x xs ~ 'True) :- (HasElem x (b ': xs) ~ 'True)
containerEntailsLarger _p1 _p2 _p3 = Sub Dict

我一直难以摆脱这个问题。这里有一种方法可以使用GADT获得好的证据,同时使用类型族和类获得好的接口。

-- Lots of extensions; I don't think I use ScopedTypeVariables,
-- but I include it as a matter of principle to avoid getting
-- confused.
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE TypeFamilies, TypeOperators #-}
{-# LANGUAGE DataKinds, PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE GADTs #-}

-- Some natural numbers
data Nat = Z | S Nat deriving (Eq, Ord, Show)

-- Evidence that a type is in a list of types
data ElemG :: k -> [k] -> * where
  Here :: ElemG x (x ': xs)
  There :: ElemG x xs -> ElemG x (y ': xs)
deriving instance Show (ElemG x xs)

-- Take `ElemG` to the class level.
class ElemGC (x :: k) (xs :: [k]) where
  elemG :: proxy1 x -> proxy2 xs -> ElemG x xs

-- There doesn't seem to be a way to instantiate ElemGC
-- directly without overlap, but we can do it via another class.
instance ElemGC' n x xs => ElemGC x xs where
  elemG = elemG'

type family First (x :: k) (xs :: [k]) :: Nat where
  First x (x ': xs) = 'Z
  First x (y ': ys) = 'S (First x ys)

class First x xs ~ n => ElemGC' (n :: Nat) (x :: k) (xs :: [k]) where
  elemG' :: proxy1 x -> proxy2 xs -> ElemG x xs

instance ElemGC' 'Z x (x ': xs) where
  elemG' _p1 _p2 = Here

instance (ElemGC' n x ys, First x (y ': ys) ~ 'S n) => ElemGC' ('S n) x (y ': ys) where
  elemG' p1 _p2 = There (elemG' p1 Proxy)

至少在简单的情况下,这似乎是可行的:

*Hello> elemG (Proxy :: Proxy Int) (Proxy :: Proxy '[Int, Char])
Here

*Hello> elemG (Proxy :: Proxy Int) (Proxy :: Proxy '[Char, Int, Int])
There Here

*Hello> elemG (Proxy :: Proxy Int) (Proxy :: Proxy '[Char, Integer, Int])
There (There Here)

这不支持您所希望的精确蕴涵,但我相信ElemGC'递归案例可能是使用此类信息约束时最接近的案例,至少在GHC 7.10中是这样。

 类似资料:
  • 安全约束是一种定义 web 内容保护的声明式方式。安全约束关联授权和或在 web 资源上对 HTTP 操作的用户数据约束。安全约束,在部署描述符中由 security-constraint 表示,其包含以下元素: web资源集合 (部署描述符中的 web-resource-collection) 授权约束 (部署描述符中的 auth-constraint) 用户数据约束 (部署描述符中的 user

  • 我试图在wildfly上保护一个演示web应用程序。我已经在单机版中定义了这个安全域。xml 然后在web-inf下,我在web.xml中定义了这个安全约束 以及jboss网站上的这些内容。xml 问题是,如果我转到/projects URL,我不会重定向到登录页面,就好像忽略了约束一样。

  • 在vinyl库中,有一个类型族,让我们询问,对于类型级别列表中的每个类型,部分应用的约束都是真的。例如,我们可以这样写: 这一切都很可爱。现在,如果我们有约束,其中是未知的,并且我们知道包含(借用Ekmett的contstraints包的语言),那么我们如何获得呢? 我问的原因是我正在处理一些函数中的记录,这些函数需要满足几个类型类约束。为此,我使用了exists包中Control.Constra

  • 我的视图控制器中有几个视图,当检测到向上滑动时向上移动,然后当检测到向下滑动时向下移动。我使用CGRectOffset通过调整y原点来强制视图移动。我现在使用IB对视图施加了约束,我不确定移动视图的最佳方法是什么,以便它们最终在iPhone 5、6和6上的正确位置。 目前我正在做这样的事情: 用比值改变常数是否更好?因此,对于上面的约束,不使用338,这样做是否更好:

  • 问题内容: 我有一个使用安全性约束来锁定对资源访问的Java Web应用程序。当Ajax请求需要身份验证时,我试图操纵HTTP 401响应,因此我创建了一个过滤器,该过滤器观察响应中的HTTP状态,并在需要时进行相应的修改。 问题是,如果需要身份验证,则直到将401发送到浏览器后,过滤器才会被调用。安全约束似乎在请求处理链中的过滤器之前。我的过滤器的url模式比任何安全约束都更通用。平台是WebS

  • 尝试跳过application.properties文件中安全约束的使用: 在Java安全和Spring配置中: 但它们随后被忽视了。 我的文件: 我的Spring Security配置: 我使用的是Spring Boot和Keyclope适配器 更新:根据下面提供的答案,我用唯一的依赖项配置了KeyClope安全性: