我如何使用具有函数依赖性的 class 来定义另一个 class 的约束?
How can I use a class that has functional dependencies to define another class's constraint?
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
class Fractional f => Point3D p f | p -> f where
x :: p -> f
y :: p -> f
z :: p -> f
class (Fractional fr, Point3D p fr, Foldable f) => HasPoints3D ps p f where
points :: ps -> f p
我制作了 Point3D
class 以涵盖 3D 点的不同实现。我做了 HasPoints3D
class 来涵盖所有有一些要点的东西。 Point3D
定义中的第二个类型变量f
由第一个类型变量p
决定。所以,我觉得HasPoints3D
这个定义没有问题,因为fr
是可以由p
.
决定的
我知道这可能会导致 typechecker loop。所以,我添加了 {-# LANGUAGE UndecidableInstances #-}
。但它不起作用,它说 Not in scope: type variable ‘fr’
。是否有另一个 haskell 扩展来完成这项工作?还是haskell就是无法应对这种情况?
就我个人而言,我倾向于避免函数依赖,而是尽可能使用类型族。我认为它通常更简单,并且避免了类似这样的问题。
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
class Fractional (F p) => Point3D p where
type F p
x :: p -> F p
y :: p -> F p
z :: p -> F p
class (Fractional (F p), Point3D p, Foldable f) => HasPoints3D ps p f where
points :: ps -> f p
我同意 chi 的观点,Points3D
一开始可能不应该是 multi-parameter class。但是,如果您对此无能为力,您仍然可以在 HasPoints3D
:
中使用关联类型族
{-# LANGUAGE ..., TypeFamilies, FlexibleContexts #-}
import Data.Kind (Type)
class ( Fractional (DirectionalComponent ps p f)
, Point3D p (DirectionalComponent ps p f)
, Foldable f ) => HasPoints3D ps p f where
type DirectionalComponent ps p f :: Type
points :: ps -> f p
顺便说一句,我发现 Point3D
抽象非常可疑。为什么你需要一个类型class?这听起来像是一种具体类型
data V3 s = V3 {x,y,z :: !s}
什么对 可能更有意义,而不是 需要具有任何特定坐标轴的特定三个维度,而是对您正在使用的 vector space 进行抽象.
同样,为什么需要HasPoints3D
class?为什么不按原样使用 f p
,根据需要分别对 f
和 p
施加适当的约束?
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
class Fractional f => Point3D p f | p -> f where
x :: p -> f
y :: p -> f
z :: p -> f
class (Fractional fr, Point3D p fr, Foldable f) => HasPoints3D ps p f where
points :: ps -> f p
我制作了 Point3D
class 以涵盖 3D 点的不同实现。我做了 HasPoints3D
class 来涵盖所有有一些要点的东西。 Point3D
定义中的第二个类型变量f
由第一个类型变量p
决定。所以,我觉得HasPoints3D
这个定义没有问题,因为fr
是可以由p
.
我知道这可能会导致 typechecker loop。所以,我添加了 {-# LANGUAGE UndecidableInstances #-}
。但它不起作用,它说 Not in scope: type variable ‘fr’
。是否有另一个 haskell 扩展来完成这项工作?还是haskell就是无法应对这种情况?
就我个人而言,我倾向于避免函数依赖,而是尽可能使用类型族。我认为它通常更简单,并且避免了类似这样的问题。
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
class Fractional (F p) => Point3D p where
type F p
x :: p -> F p
y :: p -> F p
z :: p -> F p
class (Fractional (F p), Point3D p, Foldable f) => HasPoints3D ps p f where
points :: ps -> f p
我同意 chi 的观点,Points3D
一开始可能不应该是 multi-parameter class。但是,如果您对此无能为力,您仍然可以在 HasPoints3D
:
{-# LANGUAGE ..., TypeFamilies, FlexibleContexts #-}
import Data.Kind (Type)
class ( Fractional (DirectionalComponent ps p f)
, Point3D p (DirectionalComponent ps p f)
, Foldable f ) => HasPoints3D ps p f where
type DirectionalComponent ps p f :: Type
points :: ps -> f p
顺便说一句,我发现 Point3D
抽象非常可疑。为什么你需要一个类型class?这听起来像是一种具体类型
data V3 s = V3 {x,y,z :: !s}
什么对 可能更有意义,而不是 需要具有任何特定坐标轴的特定三个维度,而是对您正在使用的 vector space 进行抽象.
同样,为什么需要HasPoints3D
class?为什么不按原样使用 f p
,根据需要分别对 f
和 p
施加适当的约束?