Si desidera sollevare funzioni del tipo Integer -> Integer -> Integer
a Foo -> Foo -> Foo
. Per farlo è possibile definire funzioni di utilità:
liftFoo :: (Integer -> Integer) -> Foo -> Foo
liftFoo f (Foo a) = Foo $ f a
liftFoo2 :: (Integer -> Integer -> Integer) -> Foo -> Foo -> Foo
liftFoo2 f (Foo a) (Foo b) = Foo $ f a b
-- and so on
allora si potrebbe utilizzare come segue:
liftFoo2 (+) (Foo 10) (Foo 5)
liftFoo2 max (Foo 10) (Foo 5)
Questo ha il vantaggio di non richiedere una proroga.
Un'altra opzione è quella di rendere la definizione della Foo
newtype più consentito in modo che si potrebbe fare è un esempio di Functor
e Applicative
:
import Control.Applicative
newtype Foo a = Foo a deriving (Eq, Show)
foo :: Integer -> Foo Integer
foo = Foo
instance Functor Foo where
fmap f (Foo a) = Foo $ f a
instance Applicative Foo where
pure = Foo
(Foo f) <*> (Foo a) = Foo $ f a
Ora si può fare come segue:
(+) <$> foo 10 <*> foo 5
max <$> foo 10 <*> foo 5
Perché foo
è specializzato nel tipo Integer
che non si perde benefici del controllo del tipo.
fonte
2014-10-06 03:43:40
Sta usando questa tecnica considerata idiomatica? –
@KevinMeredith Sì, è idiomatico. Ma solo per la tua illuminazione, dovresti provare a scrivere le istanze di 'Ord' e' Num'. – augustss