2013-04-04 7 views
6

私は幾何学ライブラリをhaskellにまとめています。私はそれをリリースするつもりはない、それは私が言語の知識を向上させるために使用している単なるプロジェクトです。タイプクリスタルとGADT

Iは次のように定義

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

参照フレームがフレームの原点とフレームの回転を表す角度を指すベクトル、定義WRT「絶対の両方であると、Localデータ型を持っています"参照のフレーム(ねえ、それは現実の世界ではありません!)。 Vectoriseジオメトリは、Vectorのリストへの可逆変換を有するものである。

次のようにローカルがFunctorのインスタンスであることができることを私に発生しました:

instance Functor Local where 
    fmap f geom = localise (frame geom) (f $ local geom) 

コンパイラは定義におけるローカライズの使用のためのVectorisableのインスタンスがないと文句を言い。無限のGHC拡張の1つを使用してこの制限を回避する方法はありますか?

EDIT:コメントで要求されたように、ここでのタイプのいくつかは、エラーがfmapの型が(a -> b) -> f a -> f bあるので、理にかなって

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' 

ある

local :: Local a -> a 
frame :: Local a -> ReferenceFrame 
localise :: (Vectorise a) => ReferenceFrame -> a -> Local a 

を使用しています。それはaVectoriseのインスタンスでなければならないと推測することができますが、bが(何らかの形で)指定できないと、fは別の型定義を定義することなく制限付き戻り値を持たなければならないことがわかりますすでにがすでに請求書に適合しているものです(または、この方法でクラスを制限すると、何らかの理由で型推論が破られる理由を説明できる人がいれば助かります)。

ps。私も、私はlocalframefmap

+1

「localise」、「local」、「frame」の種類とエラーメッセージを表示してください。私の推測では、 'Local'の'インスタンスVectorise'が欠落しています。 –

+0

完了。私はインスタンス宣言を追加しようとしましたが、それは役に立たなかった。 '' Local a''ではなく、 '' Vectorise''として宣言する必要があるのは 'f'の戻り型です。 – ovangle

答えて

13

問題の定義で逆転逆転localiseはタイプVectorise a => aを持っている2番目の引数を必要とすることであった誤植を固定していますが、fを適用するとき(入力a -> bを持っています)結果がVectoriseのインスタンスであることを保証するものではありません。local(タイプVectorise a => a)あなたが本当に望むのはFunctorのアナログで、Vectoriseという制約があるタイプでのみ動作します。

最近まで、この種のクラスを定義することはできませんでした。これはよく知られた問題であり、理由はData.SetにはFunctorまたはMonadというインスタンスがありません。しかし、最近のConstraintKinds GHC拡張など「制限付きファンクタ」とようやく可能になった:あなたはよりおよそConstraintKindsherehereを読むことができます

{-# 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) 

関連する問題