1

作成された円の半径がゼロより大きくなければならないという制約を設定する必要がある場合(半径> 0)。どうやってするの?

data Point = Point Float Float deriving (Show)  
data Radius = Radius Float deriving (Show)  
data Shape = Circle Point Radius deriving (Show)
surface :: Shape -> Float  
surface (Circle _ (Radius r)) = pi * r ^ 2  

都合がよければ、さまざまなシナリオで制約/検証を設定する方法について、さらにいくつかの例を挙げてください。たとえば、データ電話には、正規表現または特定の開始番号のセット(市外局番または国番号など)を含めることができます。

4

2 に答える 2

6

データ型のフィールドで検証を行う最も簡単な方法は、モジュールから値コンストラクターをエクスポートせず、代わりに、隠し値コンストラクターを使用してオブジェクトを実際に構築して返す前に必要なチェックを実行する関数を定義してエクスポートすることです。

エラーを報告する 2 つの方法を示す簡単な例:

module MyModule
( Radius  -- we do not export value constructors
, radius
, radius'
) where

data Radius = Radius Float deriving (Show)

radius :: Float -> Maybe Radius
radius r | r > 0     = Just (Radius r)
         | otherwise = Nothing

radius' :: Float -> Radius
radius' r | r > 0     = Radius r
          | otherwise = error "negative radius"

このようにして、モジュールのユーザーは、すべてのチェックをスキップできるようにする値コンストラクターではなく、個人的に定義した関数を介してのみ新しい値を作成できます。

于 2012-07-20T13:52:22.633 に答える