Haskell 中更高种类的类型作为类型变量
Higher kinded types as type variables in Haskell
我有一个 class:
import Linear
class Coordinate c where
rotate :: Num a => Quaternion a -> c a -> c a
translate :: Num a => V3 a -> c a -> c a
,我已经为其定义了实例
instance Coordinate V3 where
rotate _ = id
translate p = (p+)
instance Coordinate Quaternion where
rotate o = (o*)
translate _ = id
现在我想为 class 的一对成员定义一个实例。
instance (Coordinate a, Coordinate b) => Coordinate (a, b) where
rotate o (a, b) = (rotate o a, rotate o b)
translate p (a, b) = (translate p a, translate p b)
问题是这不起作用,因为编译器需要 a
和 b
的参数。但是添加类型约束,如
instance (Coordinate a, Coordinate b, Num c) => Coordinate (a c, b c) where
move p (a, b) = (move p a, move p b)
translate p (a, b) = (translate p a, translate p b)
它也不起作用,因为这会导致表达式的种类为 *
而不是 * -> *
。我可以看出以上两个都不正确,但我不确定如何解决这个问题。我想应该有某种形式的约束使 a
和 b
的 Num
类型保持相同,但我不知道从语法上看会是什么样子。
您不能为内置对类型创建此 Coordinate
class 的实例。你需要改变其中之一。
Coordinate
class可以改成以正常的Type
作为参数:
{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
import Data.Kind (Type)
class Num (Component c) => Coordinate c where
type Component c :: Type -- every Coordinate type has a Component type
rotate :: Quaternion (Component c) -> c -> c
translate :: V3 (Component c) -> c -> c
例如 V3
实例现在看起来像
instance Num a => Coordinate (V3 a) where
type Component (V3 a) = a
rotate _ = id
translate = (+)
并且 pair 实例将使用等式约束,这正是您要找的东西
instance (Coordinate a, Coordinate b, Component a ~ Component b) => Coordinate (a, b) where
type Component (a, b) = Component a -- or = Component b
rotate p (l, r) = (rotate p l, rotate p r)
translate p (l, r) = (translate p l, translate p r)
不成对,使用Product
:
import Data.Functor.Product
instance (Coordinate a, Coordinate b) => Coordinate (Product a b) where
rotate p (Pair l r) = Pair (rotate p l) (rotate p r)
translate p (Pair l r) = Pair (translate p l) (translate p r)
我有一个 class:
import Linear
class Coordinate c where
rotate :: Num a => Quaternion a -> c a -> c a
translate :: Num a => V3 a -> c a -> c a
,我已经为其定义了实例
instance Coordinate V3 where
rotate _ = id
translate p = (p+)
instance Coordinate Quaternion where
rotate o = (o*)
translate _ = id
现在我想为 class 的一对成员定义一个实例。
instance (Coordinate a, Coordinate b) => Coordinate (a, b) where
rotate o (a, b) = (rotate o a, rotate o b)
translate p (a, b) = (translate p a, translate p b)
问题是这不起作用,因为编译器需要 a
和 b
的参数。但是添加类型约束,如
instance (Coordinate a, Coordinate b, Num c) => Coordinate (a c, b c) where
move p (a, b) = (move p a, move p b)
translate p (a, b) = (translate p a, translate p b)
它也不起作用,因为这会导致表达式的种类为 *
而不是 * -> *
。我可以看出以上两个都不正确,但我不确定如何解决这个问题。我想应该有某种形式的约束使 a
和 b
的 Num
类型保持相同,但我不知道从语法上看会是什么样子。
您不能为内置对类型创建此 Coordinate
class 的实例。你需要改变其中之一。
Coordinate
class可以改成以正常的Type
作为参数:{-# LANGUAGE FlexibleContexts, TypeFamilies #-} import Data.Kind (Type) class Num (Component c) => Coordinate c where type Component c :: Type -- every Coordinate type has a Component type rotate :: Quaternion (Component c) -> c -> c translate :: V3 (Component c) -> c -> c
例如
V3
实例现在看起来像instance Num a => Coordinate (V3 a) where type Component (V3 a) = a rotate _ = id translate = (+)
并且 pair 实例将使用等式约束,这正是您要找的东西
instance (Coordinate a, Coordinate b, Component a ~ Component b) => Coordinate (a, b) where type Component (a, b) = Component a -- or = Component b rotate p (l, r) = (rotate p l, rotate p r) translate p (l, r) = (translate p l, translate p r)
不成对,使用
Product
:import Data.Functor.Product instance (Coordinate a, Coordinate b) => Coordinate (Product a b) where rotate p (Pair l r) = Pair (rotate p l) (rotate p r) translate p (Pair l r) = Pair (translate p l) (translate p r)