2010-12-29 6 views
15

Ich erwartete, dass der folgende Code mit einem Typfehler aufgrund der Verletzung von minBound und maxBound fehlschlägt. Aber wie Sie sehen können, geht es ohne Fehlermeldung.Wie verwenden Sie die Bounded-Typklasse in Haskell, um einen Typ mit einem Fließkommabereich zu definieren?

{-# OPTIONS_GHC -XTypeSynonymInstances #-} 
module Main where 

type Probability = Float 
instance Bounded Probability where 
    minBound = 0.0 
    maxBound = 1.0 

testout :: Float -> Probability 
testout xx = xx + 1.0 

main = do 
    putStrLn $ show $ testout 0.5 
    putStrLn $ show $ testout (-1.5) 
    putStrLn $ show $ testout 1.5 

Im Prelude bekomme ich diese

*Main> :type (testout 0.5) 
(testout 0.5) :: Probability 

Und an der Eingabeaufforderung ich diese:

[~/test]$runhaskell demo.hs 
1.5 
-0.5 
2.5 

Offenbar nicht Bounded Ich erkläre richtig, und ich bin sicher, dass ich mache syntaktisch etwas falsch. Es gibt in Bezug auf Bounded typeclasses nicht viele einfache Dinge in Google, daher würde jede Hilfe sehr geschätzt werden.

Antwort

21

Das ist nicht was Bounded ist für. Bounded a definiert nur die Funktionen minBound :: a und maxBound :: a. Es führt zu keiner besonderen Überprüfung oder irgendetwas.

Sie können einen beschränkten Typ mit einem sogenannten Smart-Konstruktor definieren. Das heißt:

module Probability (Probability) where 

newtype Probability = P { getP :: Float } 
    deriving (Eq,Ord,Show) 

mkP :: Float -> Probability 
mkP x | 0 <= x && x <= 1 = P x 
     | otherwise = error $ show x ++ " is not in [0,1]" 

-- after this point, the Probability data constructor is not to be used 

instance Num Probability where 
    P x + P y = mkP (x + y) 
    P x * P y = mkP (x * y) 
    fromIntegral = mkP . fromIntegral 
    ... 

So ist die einzige Art und Weise ein Probability ist zu verwenden, um die mkP Funktion schließlich (dies geschieht für Sie, wenn Sie numerische Operationen gegeben unsere Num Instanz verwenden) zu machen, die überprüft, dass das Argument in Reichweite . Aufgrund der Exportliste des Moduls ist es außerhalb dieses Moduls nicht möglich, eine ungültige Wahrscheinlichkeit zu konstruieren.

Wahrscheinlich nicht die Zweiliner, die Sie gesucht haben, aber naja.

Für zusätzliche Zusammensetzbarkeit können Sie diese Funktionalität ausschließen, indem Sie ein BoundCheck Modul anstelle von `Probability. Wie oben, außer:

So können Sie die Funktionalität, die Sie wünschen, wurde für Sie eingebaut, wenn Sie die Frage gestellt.

Um dies ableiten zu können, benötigen Sie möglicherweise die Spracherweiterung {-# LANGUAGE GeneralizedNewtypeDeriving #-}.

+0

Sehr hilfreich, vielen Dank. Eine Frage: Sie legen ein Ellipsen ("...") für die verschiedenen Arten, in denen mkP und mkBC mit vorhandenen Operatoren auf Dinge vom Num-Typ interagieren. Ich nehme an, der Zweck davon ist, arithmetische Operatoren für Dinge des Probability-Typs zu definieren, die die Ausgabe durch mkP laufen lassen, um Grenzen zu prüfen. – ramanujan

+0

@ramanujan, ja. Im Grunde nur in diesem Muster weitermachen. – luqui

+0

Falls Sie nicht wissen, wo Sie nach den 'Num'-Methoden suchen sollten: http://hackage.haskell.org/packages/archive/base/4.2.0.2/doc/html/Prelude.html#t%3ANum – luqui

Verwandte Themen