Haskell类型变量不解决

发布于 2025-01-31 15:50:48 字数 2160 浏览 1 评论 0原文

我有以下代码段,

class LatticeElement a where
    next :: a -> a -- next element     

class (Ord a, LatticeElement a) => LatticeDate a where
    prev :: a -> a -- prev date

data LatticeSlice d v = forall d v. (LatticeDate d, LatticeElement v) => LatticeSlice{date :: d, slice :: v}

map :: (v -> w) -> LatticeSlice d v -> LatticeSlice d w
map f LatticeSlice{date = d, slice = sl} = LatticeSlice{date = d, slice = f sl}

该代码会导致编译错误。现在,据我了解代码,首先,我将latticeElement作为Typeclass设置,然后将latticedate作为latticeelement typecleass,typecleass 要求类型dord的实例。

现在,我创建latticeslice,并在声明中读到“ latticeslice是类型上的数据类型dv ,仅适用于所有类型d实例化latticedatev实例化latticeElement

MAP的实例化:

src/Lattice.hs:9:77: error:
    • Couldn't match expected type ‘v’ with actual type ‘v1’
      ‘v1’ is a rigid type variable bound by
        a pattern with constructor:
          LatticeSlice :: forall d1 v1 d2 v2.
                          (LatticeDate d2, LatticeElement v2) =>
                          d2 -> v2 -> LatticeSlice d1 v1,
        in an equation for ‘map’
        at src/Lattice.hs:9:7-40
      ‘v’ is a rigid type variable bound by
        the type signature for:
          Lattice.map :: forall v w d.
                         (v -> w) -> LatticeSlice d v -> LatticeSlice d w
        at src/Lattice.hs:8:1-55
    • In the first argument of ‘f’, namely ‘sl’
      In the ‘slice’ field of a record
      In the expression: LatticeSlice {date = d, slice = f sl}
    • Relevant bindings include
        sl :: v1 (bound at src/Lattice.hs:9:38)
        f :: v -> w (bound at src/Lattice.hs:9:5)
        map :: (v -> w) -> LatticeSlice d v -> LatticeSlice d w
          (bound at src/Lattice.hs:9:1)

我认为编译器告诉我,它在(v - > w)中没有解决vLatticeslice D V中的V相同。但是我不知道为什么要这样做,或者更重要的是,该怎么办!

I have the following snippet of code

class LatticeElement a where
    next :: a -> a -- next element     

class (Ord a, LatticeElement a) => LatticeDate a where
    prev :: a -> a -- prev date

data LatticeSlice d v = forall d v. (LatticeDate d, LatticeElement v) => LatticeSlice{date :: d, slice :: v}

map :: (v -> w) -> LatticeSlice d v -> LatticeSlice d w
map f LatticeSlice{date = d, slice = sl} = LatticeSlice{date = d, slice = f sl}

Which causes a compilation error. Now, as far as I understand the code, first I set up LatticeElement as a typeclass, then LatticeDate as a specialisation of the LatticeElement typecleass, requiring that the type d is an instance of Ord.

Now I create LatticeSlice, with a declaration that I read something like "LatticeSlice is a data type on types d and v, constrained to exist only for all types d instantiating LatticeDate and v instantiating LatticeElement"

The error comes in the instantiation of map:

src/Lattice.hs:9:77: error:
    • Couldn't match expected type ‘v’ with actual type ‘v1’
      ‘v1’ is a rigid type variable bound by
        a pattern with constructor:
          LatticeSlice :: forall d1 v1 d2 v2.
                          (LatticeDate d2, LatticeElement v2) =>
                          d2 -> v2 -> LatticeSlice d1 v1,
        in an equation for ‘map’
        at src/Lattice.hs:9:7-40
      ‘v’ is a rigid type variable bound by
        the type signature for:
          Lattice.map :: forall v w d.
                         (v -> w) -> LatticeSlice d v -> LatticeSlice d w
        at src/Lattice.hs:8:1-55
    • In the first argument of ‘f’, namely ‘sl’
      In the ‘slice’ field of a record
      In the expression: LatticeSlice {date = d, slice = f sl}
    • Relevant bindings include
        sl :: v1 (bound at src/Lattice.hs:9:38)
        f :: v -> w (bound at src/Lattice.hs:9:5)
        map :: (v -> w) -> LatticeSlice d v -> LatticeSlice d w
          (bound at src/Lattice.hs:9:1)

I think that the compiler is telling me that it isn't resolving the v in (v -> w) to be the same type as the v in LatticeSlice d v. But I don't know why it is doing this, or more to the point, what to do about it!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

弥枳 2025-02-07 15:50:49

首先,forall dv。阴影latticeslice的参数。

                  d1           d2                d2                                           d2
                  |            |                 |                                            |
                  v            v                 v                                            v
data LatticeSlice d v = forall d v. (LatticeDate d, LatticeElement v) => LatticeSlice{date :: d, slice :: v}
                    ^            ^                                 ^                                      ^
                    |            |                                 |                                      |
                    v1           v2                                v2                                     v2

latticeslice的类型演示了

>> :set -fprint-explicit-foralls
>> :t +v LatticeSlice
LatticeSlice
  :: forall d1 v1 d2 v2.
     (LatticeDate d2, LatticeElement v2) =>
     d2 -> v2 -> LatticeSlice d1 v1

值构造函数的参数类型d2v2与类型构造函数的参数无关。 > d1 和v1

instance LatticeDate    ()
instance LatticeElement ()

ls :: LatticeSlice d v
ls = LatticeSlice () ()

如果删除forall量化器量化您的数据类型携带的约束,在这种情况下,我再次建议它!它等同于此GADT:

data LatticeSlice d v where
  LatticeSlice :: (LatticeDate d, LatticeElement v) => {date :: d, slice :: v} -> LatticeSlice d v

约束您的定义,MAPw参数中无法参数。仅仅因为vlatticeElement并不意味着w是。因此,我们必须见证f sl :: wlatticelement w

map :: LatticeElement w => (v -> w) -> LatticeSlice d v -> LatticeSlice d w
map f LatticeSlice{date = d, slice = sl} = LatticeSlice{date = d, slice = f sl}

这使其与functor>)的基本基础结构不相容()适用的monad ..)和bifunctorbiapplicative,..)。

这是最好的版本,如果需要晶格约束,则将它们添加到在latticeslice上操作的功能中,

data LatticeSlice d v = LatticeSlice {date :: d, slice :: v}
  deriving stock Functor

instance Bifunctor LatticeSlice where
  bimap :: (d -> d') -> (s -> s') -> (LatticeSlice d s -> LatticeSlice d' s')
  bimap f g as = bipure f g <<*>> as

instance Biapplicative LatticeSlice where
  bipure :: d -> s -> LatticeSlice d s
  bipure = LatticeSlice

  biliftA2 :: (d1 -> d2 -> d3)
           -> (s1 -> s2 -> s3)
           -> (LatticeSlice d1 s1 -> LatticeSlice d2 s2 -> LatticeSlice d3 s3)
  biliftA2 (·) (×) (LatticeSlice d1 s1) (LatticeSlice d2 s2) =
    LatticeSlice (d1 · d2) (s1 × s2)

请观看Edward Kmett的类型类与世界有关更多信息。

First of all the forall d v. shadows the arguments of LatticeSlice.

                  d1           d2                d2                                           d2
                  |            |                 |                                            |
                  v            v                 v                                            v
data LatticeSlice d v = forall d v. (LatticeDate d, LatticeElement v) => LatticeSlice{date :: d, slice :: v}
                    ^            ^                                 ^                                      ^
                    |            |                                 |                                      |
                    v1           v2                                v2                                     v2

The type of LatticeSlice demonstrates this

>> :set -fprint-explicit-foralls
>> :t +v LatticeSlice
LatticeSlice
  :: forall d1 v1 d2 v2.
     (LatticeDate d2, LatticeElement v2) =>
     d2 -> v2 -> LatticeSlice d1 v1

The argument types of value constructor has d2 and v2 has nothing to do with the arguments of the type constructor d1 and v1:

instance LatticeDate    ()
instance LatticeElement ()

ls :: LatticeSlice d v
ls = LatticeSlice () ()

If you remove the forall quantifiers your datatype is carrying around the constraint, in this case I recommend againt it! It is equivalent to this GADT:

data LatticeSlice d v where
  LatticeSlice :: (LatticeDate d, LatticeElement v) => {date :: d, slice :: v} -> LatticeSlice d v

The constraint encumbers your definitions, map can not be parametric in the w argument. Just because v is a LatticeElement does not mean w is. Therefore we must witness that f sl :: w is a LatticeElement w:

map :: LatticeElement w => (v -> w) -> LatticeSlice d v -> LatticeSlice d w
map f LatticeSlice{date = d, slice = sl} = LatticeSlice{date = d, slice = f sl}

This makes it incompatible with the basic infrastructure like Functor (Applicative, Monad..) and Bifunctor (Biapplicative, ..).

This is the best version, if you need lattice constraints you add them to the functions that operate on LatticeSlice

data LatticeSlice d v = LatticeSlice {date :: d, slice :: v}
  deriving stock Functor

instance Bifunctor LatticeSlice where
  bimap :: (d -> d') -> (s -> s') -> (LatticeSlice d s -> LatticeSlice d' s')
  bimap f g as = bipure f g <<*>> as

instance Biapplicative LatticeSlice where
  bipure :: d -> s -> LatticeSlice d s
  bipure = LatticeSlice

  biliftA2 :: (d1 -> d2 -> d3)
           -> (s1 -> s2 -> s3)
           -> (LatticeSlice d1 s1 -> LatticeSlice d2 s2 -> LatticeSlice d3 s3)
  biliftA2 (·) (×) (LatticeSlice d1 s1) (LatticeSlice d2 s2) =
    LatticeSlice (d1 · d2) (s1 × s2)

Watch Edward Kmett's Type Classes vs. the World for more information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文