2016-12-27 11 views
3

NB:以下で定義するタイプは、この質問の目的のための便利な例です。ハスケルで私自身の複素数の定義をロールバックする必要はないと確信しています。(部分)レコードセレクタを「拡張する」方法


私はここに右の専門用語を使用している場合、私は知らないが、以下のセレクタrが、私は「部分的」レコードセレクタによって何を意味するかのANE例です。

data Complex = Polar  { r :: Float, y :: Float } 
      | Rectangular { x :: Float, y :: Float } 
      deriving Show 

rには適用できないため「部分的」ですComplex値;例えば

r $ Polar 3 0 
-- 3.0 

...しかし、この場合

r $ Rectangular 3 0 
-- *** Exception: No match in record selector r 

が、しかし、r $ Rectangular x yための賢明な定義はつまり、あります:

-- assuming {-# LANGUAGE RecordWildCards #-} 
r :: Complex -> Float 
r Rectangular { .. } = sqrt $ (x * x) + (y * y) 

GHCiのはmultiple declarations of ‘r’で、rのこの定義を拒否しますエラー。

を拡張する方法はありますか。任意のComplexの値に適用できますか?もちろん


、私は

-- assuming {-# LANGUAGE RecordWildCards #-} 
modulus :: Complex -> Float 
modulus Polar  { .. } = r 
modulus Rectangular { .. } = sqrt $ (x * x) + (y * y) 

のようなものを定義することができることを実現...しかし、私は既存のセレクタrを拡張することが可能であるかどうかを知りたいです。

答えて

5

いいえ、そのようなレコードセレクタは決して導入しないでください。私は

type ℝ = Float -- Note that Double is usually more sensible 

newtype S¹ = S¹ {ϑ :: ℝ} -- in [-π, π[ 
newtype ℝPlus = ℝPlus {posℝ :: ℝ} -- in [0, ∞[ 

data Complex = Polar ℝPlus S¹ 
      | Rectangular ℝ ℝ 
     deriving Show 

この方法としてこれを書きたい、でも、そのような「非記録タイプ」のために...など解凍するためにどのような部分的なレコードセレクタの形式に誤りの可能性、また、無混乱あなたは、ありません

import Control.Lens 

r :: Lens' Complex ℝPlus 
r = lens get set 
where get (Polar r _) = r 
     get (Rectangular x y) = ℝPlus . sqrt $ x^2 + y^2 
     set (Polar _ θ) r = Polar r θ 
     set (Rectangular x y) (ℝPlus r) = Rectangular (x * η) (y * η) 
     where η = r/sqrt (x^2 + y^2) 
+1

あなたは本当にこのユニコード構文に慣れています – luqui

関連する問題