【发布时间】:2016-03-29 20:47:48
【问题描述】:
尝试创建一个适用于元组的 Vector 类型类我遇到了一些问题
{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
class Vector v where
type Scalar v :: *
vplus :: v -> v -> v
vmult :: v -> Scalar v -> v
vdot :: v -> v -> Scalar v
instance Num a => Vector (a, a) where
type Scalar (a,a) = a
(a, b) `vplus` (c, d) = (a + c, b + d)
(a, b) `vmult` m = (a * m, b * m)
(a, b) `vdot` (c, d) = a * c + b * d
问题是我需要明确的 GHC 类型声明才不会混淆。这当然是一个小小的不便,除了vdot 似乎根本不想工作。
res :: Int
res = (2, 3) `vdot` (5, 5)
-- error: Couldn't match expected type 'Int' with actual type 'Scalar (t0, t1)'
-- The type variables 't0', 't1' are ambiguous
如果我这样做,这个错误就会消失:
res :: Int
res = ((2, 3) :: (Int, Int)) `vdot` (5, 5)
但是现在我们已经达到了冗长代码的境界,以至于它不再实用了。 Haskell 应该是美丽而简洁的;非显式类型地狱
我会假设 GHC 能够自行解析 type Scalar (a, a) = a,但即使我完全删除了实例声明,错误仍然存在。当 Vector (Int, Int) 是唯一可用的实例时,它甚至会抱怨。
那么这里发生了什么?有没有办法让它完美地工作?
【问题讨论】:
标签: haskell type-inference typeclass type-families