haskell - 约束种类: Pass multiple constraints

标签 haskell constraint-kinds

当我在 haskell 中有如下数据类型时:

data A ctx = A (forall a. ctx a => a -> a)

然后我可以将作用于给定类的类型值的函数放入此数据类型中:

> A (+3) :: A Num
A (+3) :: A Num :: A Num

但是是否也可以将具有多个约束的函数放入此数据类型中?我试过这个:

> :t ((+ 3) . succ)
((+ 3) . succ) :: (Enum c, Num c) => c -> c
> :t A ((+ 3) . succ) :: A (Enum,Num)
  Expecting one more argument to `Enum'
  In an expression type signature: A (Enum, Num)
  In the expression: A ((+ 3) . succ) :: A (Enum, Num)

所以这不起作用。我想要做的事情怎么可能,或者不可能?我知道一种解决方案是使用“虚拟”数据类型和类型系列,但如果有其他方法,我不想这样做,因为它很复杂。另外,在这个例子中,我可以只使用 (+1) 而不是 succ,但在更复杂的情况下,不可能只对一个类进行这种转换。

最佳答案

我找到了一种方法来概括将多个类合并为一个类的想法。虽然使用起来很别扭,但它确实有效。

{-# LANGUAGE ConstraintKinds       #-}
{-# LANGUAGE EmptyDataDecls        #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE KindSignatures        #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverlappingInstances  #-}
{-# LANGUAGE RankNTypes            #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TypeOperators         #-}
{-# LANGUAGE UndecidableInstances  #-}
module Test where

import GHC.Exts

data (:>+<:) ctx1 ctx2 a where
  C'C :: (ctx1 a, ctx2 a) => (ctx1 :>+<: ctx2) a

data (:++:) (ctx1 :: * -> Constraint) (ctx2 :: * -> Constraint) = C

class Ctx2 c1 c2 a where
  useCtx :: c1 :++: c2 -> a -> ((c1 :>+<: c2) a -> b) -> b

instance (c1 a, c2 a) => Ctx2 c1 c2 a where
  useCtx _ a f = f C'C

fC :: (Ctx2 Num Enum a) => a -> a
fC a = useCtx (C :: Num :++: Enum) a $ \C'C  -> 3 + succ a

data A ctx = A 
  { call :: forall a. ctx a => a -> a
  }

main = print $ call (A fC :: A (Ctx2 Num Enum)) 3

应该可以使用约束别名来定义 Ctx3、Ctx4...

关于haskell - 约束种类: Pass multiple constraints,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17254057/

相关文章:

haskell - 没有因使用 `from' 而产生的 (Generic (f a)) 实例

haskell - 是否可以使用约束类型在 Haskell 中模拟有限形式的交集类型?

haskell - 约束约束

haskell - Numeric.AD 函数中可接受的类型

haskell - 检查 type 是否实例化 GHCI 中的类型类

json - Haskell:将 JSON 数据解析为 Map 或元组列表?

haskell - GHC 什么时候可以推断出约束变量?

haskell - 约束元组的可键入实例

performance - 为什么头尾模式匹配比索引快得多?

haskell - Eff 中的多个 IO 效果(或其他可组合效果的方式)