你想解除功能類型Integer -> Integer -> Integer
至Foo -> Foo -> Foo
。要做到這一點,你可以定義效用函數:
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
然後如下,你可以使用它:
liftFoo2 (+) (Foo 10) (Foo 5)
liftFoo2 max (Foo 10) (Foo 5)
這是無需使用擴展的優勢。
另一種選擇是使Foo
NEWTYPE的定義更容許這樣你可以把它的Functor
和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
現在你可以做到以下幾點:
(+) <$> foo 10 <*> foo 5
max <$> foo 10 <*> foo 5
由於foo
專門針對Integer
類型,因此您不會丟失任何類型檢查的好處。
正在使用這種技術認爲慣用? – 2014-10-06 10:27:01
@KevinMeredith是的,這是慣用的。但僅僅爲了你自己的啓發,你應該嘗試自己編寫'Ord'和'Num'實例。 – augustss 2014-10-06 10:46:07