2017-06-21 3 views
0

私は、2Dジオメトリでいくつかの慰めを得るためにいくつかの関数を作成しました。 この例では、私はGeom2D from CubicBezier packageを使用します。Haskell:制約内の可変でない可変引数

私のプログラムの完全なコード:https://gist.github.com/nskeip/3784d651ac646a67c5f246f048949af4

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-} 
import Geom2D 

left :: (Num a) => Point a -> a -> Point a 
left (Point x y) n = Point (x - n) y 

right :: (Num a) => Point a -> a -> Point a 
right (Point x y) n = Point (x + n) y 

up :: (Num a) => Point a -> a -> Point a 
up (Point x y) n = Point x (y - n) 

down :: (Num a) => Point a -> a -> Point a 
down (Point x y) n = Point x (y + n) 

彼らは次のように動作します:

Pointは、次のように定義されて
> (Point 0 0) `up` 10 
Point 0.0 -10.0 

data Point a = Point { 
    pointX :: !a, 
    pointY :: !a 
    } deriving (Eq, Ord, Functor, Foldable, Traversable) 

、すべてそれまでは、私大丈夫でした思った: "ねえ、それは機能を作ることがいいだろうS(actualy、事業者は)​​Lineのようなthigsと連携 - だけでなく、Point

は、だから私は(簡単なthigsを保つためにleftrightを取っていない)クラスを宣言:

class Num n => Moving p n where 
    up' :: n -> p -> p 
    down' :: n -> p -> p 

    up' n = down' (-n) 
    down' n = up' (-n) 

そして用MovingのインスタンスPoint aデータタイプ:

instance Num a => Moving (Point a) a where 
    up' n (Point x y) = Point x (y - n) 

しかし、私はそれを使用しようとすると、私はエラーだ:

✗ ghci ./uno.hs 
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help 
[1 of 1] Compiling Main    (uno.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> let p = Point { pointX = 0, pointY = 0 } 
*Main> up' 10 p 

<interactive>:3:1: 
    Non type-variable argument in the constraint: Moving (Point a) n 
    (Use FlexibleContexts to permit this) 
    When checking that ‘it’ has the inferred type 
     it :: forall n a. (Num a, Moving (Point a) n) => Point a 

私は多くのことを混乱させます:私はFlexibleContextsプラグマを頭のプラグマリストに入れましたが、ghcuはまだそれを含めるように勧めています。

パラメトリック多型が機能するようにクラス/インスタンスを修正するにはどうすればよいですか? :)

+1

しかし、おそらく 'ghci'にはないので、' ghci -XFlexibleContexts file.hs'でそれを実行するべきです。 –

答えて

1

And the thing that confuses me much: I put the FlexibleContexts pragma to the pragma listing in the head, but ghcu still suggest me to get it included.

これは、モジュール自体の拡張機能のみを有効にします。このコードをGHCiに書くには、GHCiで拡張機能を有効にする必要があります::set -XFlexibleContexts

しかし、これは問題の一部に過ぎません。クラスpnを決定する必要があります:Point aaで上下に移動できますか?しかし、そのままでは、より多くのMoving (Point a) SomeOtherTypeインスタンスを定義することを止めるものはありません。だから、推測型のanは完全に無関係です。これは、同じpn異なる持つインスタンスが存在しないことを正確に意味する

class Num n => Moving p n | p -> n where 

を言うためにクラス宣言をFunctionalDependencies extensionを添加して変化させることによって固定することができます。

私はそれが機能するには十分だと思います。コードは任意の数値aを許可するため、未定義ですが、デフォルトのルールではIntegerが選択されます。

+0

ありがとう!私はあなたのソリューションを使用しようとします。 –

+0

うん、FunctionalDependenciesとFlexibleContentsは魔法をやっている:) –

関連する問題