“Int - >的Monoid实例分辨率Int - > Ordering`

时间:2014-04-27 08:34:21

标签: haskell typeclass

我打算在明天向Haskell提供的小型介绍中展示一个类型类的强大功能的例子。

我以为我会仔细检查我要呈现的内容,因为我并非百分之百的自信。

所以,我们说我有两个功能:

firstSort :: Int -> Int -> Ordering
firstSort a b = compare (even a) (even b)

secondSort :: Int -> Int -> Ordering
secondSort = compare

现在,由于他们的Monoid实例,我可以将这两种结合起来:

sort :: Int -> Int -> Ordering
sort = firstSort <> secondSort

现在我要确认的是两种情况mappend期间使用的过程。

据我所知,它的工作原理如下:

  • 首先是实例:

    instance Monoid b => Monoid (a -> b) where
            mempty _ = mempty
            mappend f g x = f x `mappend` g x
    

    被使用。这是通过使用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)
    
  • 然后是实例:

    instance Monoid Ordering where
            mempty         = EQ
            LT `mappend` _ = LT
            EQ `mappend` y = y
            GT `mappend` _ = GT
    

    mappendfirstSort

  • 的结果一起使用指定的secondSort

因此,总结一下,它会将Monoid b => Monoid (a -> b)个实例与b = Orderinga = (Int -> Int)以及之后的Monoid Ordering个实例相匹配。

这是对的吗?

2 个答案:

答案 0 :(得分:7)

是。你已经正确地结束了。

由于Int -> Int -> Ordering是curry,它可以看作是一个参数的函数,它返回另一个函数。即:

Int -> (Int -> Ordering)

因此,编译器分三步解析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

答案 1 :(得分:7)

我们来看看。我不认为你想要的a(Int -> Int)因为当没有parantheses时函数类型与右边相关联。在您的情况下,类型是

firstSort :: Int -> (Int -> Bool)
secondSort :: Int -> (Int -> Bool)

所以,这里有一些有趣的事情。当你连接这两个函数时,它实际上是两次!首先,a只是第一个IntbInt -> Bool,所以我们必须使用Int -> Bool的Monoid结构。但要做到这一点,我们必须再做同样的事情,因此aIntbBool

firstSort <> secondSort = \a -> (firstSort a) <> (secondSort a) 
                        = \a -> (\b -> (firstSort a b) <> (secondSort a b))

但最终结果仍然与你得出的结果相同:

                        = \a b -> (firstSort a b) <> (secondSort a b)