我打算在明天我将给Haskell的一个小介绍中展示类型类的强大功能的一个例子.
我以为我会仔细检查我要呈现的内容,因为我不是100%自信.
所以,假设我有两个功能:
firstSort :: Int -> Int -> Ordering
firstSort a b = compare (even a) (even b)
secondSort :: Int -> Int -> Ordering
secondSort = compare
Run Code Online (Sandbox Code Playgroud)
现在,由于他们的Monoid实例,我可以将这两种结合起来:
sort :: Int -> Int -> Ordering
sort = firstSort <> secondSort
Run Code Online (Sandbox Code Playgroud)
现在我要确认的是mappend两种类型中使用的过程.
根据我的理解,它的工作方式如下:
首先是实例:
instance Monoid b => Monoid (a -> b) where
mempty _ = mempty
mappend f g x = f x `mappend` g x
Run Code Online (Sandbox Code Playgroud)
用来.这是通过实例化a该实例来完成的(Int -> Int).此外,声明mappend让我困惑了一段时间,因为它需要3个参数而不是2但后来我记得那(a -> b) -> (a -> b) -> (a -> b)实际上是相同的(a -> b) -> (a -> b) -> a -> b.
感谢这个实例,我们得到的firstSort <> secondSort是:
\a b -> (firstSort a b) <> (secondSort a b)
Run Code Online (Sandbox Code Playgroud)那么实例:
instance Monoid Ordering where
mempty = EQ
LT `mappend` _ = LT
EQ `mappend` y = y
GT `mappend` _ = GT
Run Code Online (Sandbox Code Playgroud)
与mappend结果一起使用firstSort和secondSort
所以,概括起来讲,这将匹配Monoid b => Monoid (a -> b)实例与b = Ordering和a = (Int -> Int)事后的Monoid Ordering实例.
那是对的吗?
是.你已经正确地结束了.
由于Int -> Int -> Ordering是curry,它可以看作是一个参数的函数,它返回另一个函数.即:
Int -> (Int -> Ordering)
Run Code Online (Sandbox Code Playgroud)
因此,编译器Monoid分三步解析实例:
Value Type | Monoid Instance
--------------------------|---------------------------
Int -> (Int -> Ordering) | instance Monoid b => Monoid (a -> b)
Int -> Ordering | instance Monoid b => Monoid (a -> b)
Ordering | instance Monoid Ordering
Run Code Online (Sandbox Code Playgroud)
让我们来看看.我不认为a你想要的是(Int -> Int)因为当没有parantheses时函数类型与右边相关联.在你的情况下,类型是
firstSort :: Int -> (Int -> Bool)
secondSort :: Int -> (Int -> Bool)
Run Code Online (Sandbox Code Playgroud)
所以,这里有一些有趣的事情.当你连接这两个函数时,它实际上是两次!首先,a它只是第一个Int而且b是Int -> Bool,所以我们必须使用Monoid结构Int -> Bool.但要做到这一点,我们必须再做同样的事情,所以a是Int和b是Bool.
firstSort <> secondSort = \a -> (firstSort a) <> (secondSort a)
= \a -> (\b -> (firstSort a b) <> (secondSort a b))
Run Code Online (Sandbox Code Playgroud)
但最终结果仍然与你得出的结果相同:
= \a b -> (firstSort a b) <> (secondSort a b)
Run Code Online (Sandbox Code Playgroud)