私のプログラムで型の安全性を高めるために、いくつかのバージョンのものを定義したいが、異なる型を定義したいと思う。たとえば、私はNum
のインスタンスになりたいいくつかの二変量値を持っていますが、すべてが異なるタイプでなければなりません。だから、私がやったことは、1つの型変数を持つnewtypeを作成し、それに基づいて新しい型を宣言することです。しかし、私は今、両方のコンストラクタを常に使用しなければならないというのは、ちょっと面倒です。これを回避する方法はありますか?Haskell:型セーフな同義語用のnewtype:2つのコンストラクタを使用していますか?
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Bivar t = Bivar (t,t) deriving (Show, Eq)
instance (Num t) => Num (Bivar t) where
(+) (Bivar (x1,y1)) (Bivar (x2,y2)) = Bivar (x1+x2, y1+y2)
(-) (Bivar (x1,y1)) (Bivar (x2,y2)) = Bivar (x1-x2, y1-y2)
(*) (Bivar (x1,y1)) (Bivar (x2,y2)) = Bivar (x1*x2, y1*y2)
abs (Bivar (x1,y1)) = Bivar (abs x1, abs y1)
fromInteger i = Bivar (fromInteger i, fromInteger i)
signum (Bivar (x1,y1)) = Bivar (signum x1, signum y1)
newtype BivarNode = BivarNode (Bivar Int) deriving (Show, Eq, Num)
newtype BivarVal = BivarVal (Bivar Double) deriving (Show, Eq, Num)
newtype HBivarVal = HBivarVal (Bivar Double) deriving (Show, Eq, Num)
-- This is annoying:
a1 = BivarVal (Bivar (1.0, 2.0))
a2 = HBivarVal (Bivar (1.0, 2.0))
b = BivarNode (Bivar (1,2))
-- is there a way so that I can write it this way?
aa1 = BivarVal (1.0, 2.0)
aa2 = HBivarVal (1.0, 2.0)
bb = BivarNode (1,2)
ありがとう!
EDIT:
元の質問に展開するには、私も、パターンの型の名前を使用したいと一致し、
myFunction :: HBivarVal -> Double
myFunction (HBivarVal (Bivar (x,y))) = x
の線に沿って何かがあまりにも可能ですか?
2番目の質問には、ビューパターンを使用します。 –
@ ThomasM.DuBuissonありがとう、それをチェックします – Paul
新しいタイプのラッピングペアは実際にあなたに何も得られません(GHCはnewtypeラッパーを最適化しますが、すべてのパターンマッチングはまだペアを使用する必要があります)ので、 'data Bivar t = Bivar ttは同等で、キーストロークはわずかです... –