类型类和GADT

我在haskell中放置了一个几何库。 我不打算发布它,这只是一个我用来提高我对该语言知识的项目。

我有一个Local数据类型,具有以下定义

data Local a where
    MkLocal :: (Vectorise a) => ReferenceFrame -> a -> Local a

参考框架是一个指向框架起点的矢量和一个代表框架旋转的角度,它们都被定义为“绝对”参考框架(嘿,它不是现实世界!)。 Vectorise几何是一个可逆变换到Vector列表中的几何。

我想到Local可能是Functor一个实例,如下所示:

instance Functor Local where
     fmap f geom = localise (frame geom) (f $ local geom)

但是编译器抱怨在定义中没有Vectorisable的实例用于本地化。 使用无数的GHC扩展之一有没有办法解决这个限制?

编辑:根据评论的要求,这里是一些使用的类型

local :: Local a -> a
frame :: Local a -> ReferenceFrame
localise :: (Vectorise a) => ReferenceFrame -> a -> Local a

错误是

No instance for (Vectorise b)
  arising from a use of `localise'
In the expression:
  localise (frame geom) (f $ local geom)
In an equation for `fmap':
    fmap f lgeom = localise (frame geom) (f $ local geom))
In the instance declaration for `Functor Local'

这是有道理的,因为fmap的类型是(a -> b) -> fa -> fb 。 它可以推断出a必须是Vectorise一个实例,但我想知道它是如何推断b ,除非我可以指定(以某种方式)我可以告诉编译器f必须有限制的返回类型,而不需要定义另一个typeclass已经是一种几乎符合法案的条款(或者,如果有人能够有助于解释为什么以这种方式限制类别会以某种方式破坏类型推断)。

PS。 我还修复了一个错误,我在fmap的定义中颠倒了localframe


问题是localise需要它的第二个参数具有类型Vectorise a => a ,但是当您将f (它具有类型a -> b )应用于local (类型Vectorise a => a )的结果时,没有保证结果值的类型是Vectorise一个实例。 你真正想要的是一个Functor的模拟,它只适用于具有Vectorise约束的类型。

直到最近,还不可能定义这样的类型类。 这是一个众所周知的问题,也是Data.Set没有FunctorMonad实例的原因。 然而,随着最近ConstraintKinds GHC的扩展,这些“受限函子”终于成为可能:

{-# LANGUAGE GADTs, ConstraintKinds, TypeFamilies #-}
module Test
       where

import GHC.Exts (Constraint)

data ReferenceFrame = ReferenceFrame

class Vectorise a where
  ignored :: a

data Local a where
    MkLocal :: ReferenceFrame -> a -> Local a

local :: Vectorise a => Local a -> a
local = undefined

frame :: Local a -> ReferenceFrame
frame = undefined

localise :: (Vectorise a) => ReferenceFrame -> a -> Local a
localise = undefined

class RFunctor f where
  type SubCats f a :: Constraint
  type SubCats f a = ()
  rfmap ::  (SubCats f a, SubCats f b) => (a -> b) -> f a -> f b

instance RFunctor Local where
  type SubCats Local a = Vectorise a
  rfmap f geom = localise (frame geom) (f $ local geom)

你可以在这里和这里阅读更多关于ConstraintKinds信息。

链接地址: http://www.djcxy.com/p/43471.html

上一篇: Typeclasses and GADTs

下一篇: Haskell: Typeclass implies other typeclass