試圖創造一個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)
是唯一可用的實例。
那麼這裏發生了什麼?有沒有辦法讓這個工作很好?
我想如果它說'標量(a,a)'和'向量(a,a)'唯一可用的類型是'a'。所以如果'a'是一個Int,其他每個'a'的實例都必須是Int –
我想你只是假設你的'Vector(a,a)'實例將被選中。關鍵是沒有任何東西會強制它被選中,事實上,你可以添加第二個不重疊的實例,如果在'res'中使用,也會進行類型檢查。 GHC從不「只是假設」一個實例將被選中,只是因爲它具有實例可用,它需要使用我的答案的後半部分概述的邏輯來查找實例。 –
但是如果它是唯一可用的實例,那麼它怎麼不一定選擇那個實例呢?是不是有一個方形的洞和一個不能進去的正方形,因爲它可能是一個圓圈? –