假设我有以下内容newtype
:
newtype Foo = Foo Integer deriving (Eq, Show)
有没有简洁的方法来添加两个Foo
:
(Foo 10) + (Foo 5) == Foo 15
或获得最大值:
max (Foo 10) (Foo 5) == Foo 5
?
我很好奇是否可以轻松使用a
for的功能newtype a
而不是:
addFoo :: Foo -> Foo -> Foo
addFoo (Foo x) (Foo y) = Foo $ x + y
Run Code Online (Sandbox Code Playgroud)
jbe*_*man 12
就像haskell98知道如何为你派生那些Eq
和Show
实例一样,你可以打开GeneralizedNewtypeDeriving
ghc 的扩展来获得你需要的Num
和Ord
实例:
Prelude> :set -XGeneralizedNewtypeDeriving
Prelude> newtype Foo = Foo Integer deriving (Eq, Show, Num, Ord)
Prelude> (Foo 10) + (Foo 5) == Foo 15
True
Prelude> max (Foo 10) (Foo 5) == Foo 5
False
Run Code Online (Sandbox Code Playgroud)
Aad*_*hah 10
您想要将类型的函数提升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
Run Code Online (Sandbox Code Playgroud)
然后你可以使用它如下:
liftFoo2 (+) (Foo 10) (Foo 5)
liftFoo2 max (Foo 10) (Foo 5)
Run Code Online (Sandbox Code Playgroud)
这具有不需要扩展的优点.
另一种选择是使定义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
Run Code Online (Sandbox Code Playgroud)
现在您可以执行以下操作:
(+) <$> foo 10 <*> foo 5
max <$> foo 10 <*> foo 5
Run Code Online (Sandbox Code Playgroud)
因为foo
是专门的Integer
类型,你不会失去任何类型检查的好处.
归档时间: |
|
查看次数: |
154 次 |
最近记录: |