【问题标题】:How can I coerce constraints?如何强制约束?
【发布时间】:2021-05-16 13:40:35
【问题描述】:

是否有任何机制可以在 Haskell 中强制约束(除了我希望有效的 unsafeCoerce)?

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
module CatAdjonctionsSOQuestion where

import Data.Proxy
import Data.Tagged
import Unsafe.Coerce

newtype K a ph = K {unK :: a} -- I would want c a => c ((K a) i) for any c :: Constraints

-- I could do any possible instance by hand
deriving via a instance Semigroup a => Semigroup ((K a) i)

-- I want them all
-- deriving via a instance c ((K a) i) -- Instance head is not headed by a class: c (K a i)

data Exists c where
  Exists :: c a => a -> Exists c

data ExistsKai c i where
  ExistsKai :: c ((K a) i) => Proxy a -> ExistsKai c i

ok :: forall x c i. (forall x. (forall a. c a => a -> x) -> x) -> (forall a. c ((K a) i) => Tagged a x) -> x
ok s k =
  let e = (s Exists :: Exists c)
   in let f = unsafeCoerce e :: ExistsKai c i
       in case f of (ExistsKai (Proxy :: Proxy a)) -> unTagged (k @a)

【问题讨论】:

  • 你到底在问什么? instance c a => c ((K a) b) 给我一个非常糟糕的主意。但这不是标题似乎要问的。那么,...?
  • 另外,ok 的签名与那些阴影类型变量等等看起来很糟糕。你不能再简化一下场景吗? (而且我个人发现forall 更清楚地表明了这样的签名。)
  • aK a i“相同”。每个实例a 拥有,K a I 也应该拥有。我可以将deriving via 用于我想的任何约束c,这要归功于强制。所以我想将a 上的所有实例提升到K a i
  • 我同意,这是一个丑陋的签名.. 不知道如何使它更好。我可以用proxy a 替换a

标签: haskell deriving derivingvia


【解决方案1】:

稍作修改以使其友好检查,您要求

newtype K a ph = K {unK :: a}
-- I would want c a => c ((K a) i)
-- for any c :: Type -> Constraint

你绝对不能得到它,现在或永远,因为它是无效的。考虑

(~) Bool :: Type -> Constraint

现在(~) Bool Bool 成立,但你永远无法达到(~) Bool (K Bool i)

如果没有等式约束呢?好吧,我也可以这样做,使用 Leibniz 等式:

class Bar a where
  isBool :: f a -> f Bool

instance Bar Bool where
  isBool = id

但是没有办法写出instance Bar (K Bool i)isBool 没有触底。

【讨论】:

  • 很好的反例。改写:deriving via选择将采用的分支。选择后,将引入更多方程进行求解。而那些没有理由被证实。 coerce (因此通过)只谈论数据 representation 根本不谈论附加到数据类型的方程。我们没有一种语言可以让这些选择出可以安全的选择(比如没有上下文)。每个数据/新类型都是独立的。
  • (不相关:希望您看看我的最新答案/编辑,在当前foldr1 实现中存在一个疑似错误,foldr1 (||) (True : undefined) 显然不同,令我惊讶。真的吗?.. ..foldr (||) undefined (True : undefined) 没有。我认为两者应该是等价的。)
  • 由于技术原因,我们无法对 haskell 强制我们引入的子集执行此操作,这太糟糕了。就像当你有一个类型 (f a, b) 并且你需要(haskell 要求你)将它统一视为一对应用类型构造函数 (f a, I b)I 一些身份新类型。
  • @nicolas,我认为我们可能很快就会更多地访问类字典的显式表示(尽管我没有足够关注详细的建议),所以也许最终。
猜你喜欢
  • 2012-12-05
  • 1970-01-01
  • 2011-09-07
  • 2015-07-13
  • 2010-12-15
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多