2013-04-04 39 views
6

我把一起在Haskell幾何庫。我不打算髮布它,這只是一個我用來提高我對該語言知識的項目。類型類和GADTs

我有一個Local數據類型,具有以下定義

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

的參考幀是一個向量指向幀的原點和表示幀的旋轉角,這兩個定義WRT「絕對「參考框架(嘿,這不是真正的世界!)。一個Vectorise幾何是一個可逆轉換成Vector列表。

它發生,我認爲當地如下可能是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) -> f a -> f b。它可以推斷a必須是Vectorise一個實例,但我不知道它如何可以推斷,b是,除非我可以指定(不知),我可以告訴大家,f必須有限制的返回類型沒有定義時,有另一種類型類的編譯器已經是一個幾乎符合該法案已經(或交替,如果有人能幫忙,解釋爲什麼以這種方式會破壞類型推斷在某種程度上限制類)。

ps。我也定了,我已經扭轉localframe逆轉的fmap

+1

請告訴我們的類型'localise','local'和'frame'和錯誤信息,你得到。我的猜測是你缺少'Local Vector'的實例Vectorise'。 – 2013-04-04 11:03:39

+0

完成。我嘗試添加實例聲明,但它沒有幫助。這是'f'的返回類型,我需要聲明爲'Vectorise',據我所知,而不是'Local a'。 – ovangle 2013-04-04 12:06:14

回答

13

問題的定義是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) 

你可以閱讀更多關於ConstraintKindsherehere