什么是FlexibleContexts扩展适合?你能用一个简单的例子解释一下吗?

问题描述 投票:32回答:3

我试图通过搜索网页来了解FlexibleContexts扩展正在做什么,这些网页可以解释为凡人(例如,像我一样读过LYHFGG的人),但我没有找到任何这样的资源。

因此,我向专家们询问这个话题:有人可以解释一下这个扩展的作用,它为什么存在,并给出一两个简单的例子,说明如何以及为什么要使用它?

此外,如果我正在阅读其他人的代码which使用此扩展,那么为了理解使用此扩展编写的代码,我应该知道哪些扩展名?

haskell ghc
3个回答
51
投票

如果没有FlexibleContexts,函数定义中的所有类型类约束都必须具有类型变量。例如:

add :: Num a => a -> a
add = (+)

其中a是类型变量。启用FlexibleContexts后,您可以在类型类中包含任何类型。

intAdd :: Num Int => Int -> Int
intAdd = (+)

这个例子非常人为,但它是我能想到的最简单的例子。 FlexibleContexts通常只与MultiParamTypeClasses一起使用。这是一个例子:

class Shower a b where
  myShow :: a -> b

doSomething :: Shower a String => a -> String
doSomething = myShow

在这里你可以看到我们说我们只想要一个Shower a String。如果没有FlexibleContextsString必须是类型变量而不是具体类型。


6
投票

通常它与MultiParamTypeClasses扩展一起使用,例如当你使用mtl库时你可能会写

doSomethingWithState :: MonadState MyState m => m ()
doSomethingWithState = do
    current <- get
    let something1 = computeSomething1 current
        something2 = computeSomething2 current something1
    put something2

MonadReaderMonadWriter一样,以及其他类似的类型。没有FlexibleContexts你就不能使用这个约束。

(请注意,这个答案是基于@DiegoNolan's,但重写为使用一个对LYAH读者有意义的现有库)。


3
投票

除了上面提到的那些之外,我发现了它的用途:它导致GHC更清晰的错误消息。例如。一般,

Prelude> max (1, 2) 3

<interactive>:1:1: error:
    • Non type-variable argument in the constraint: Num (a, b)
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall a b.
              (Num (a, b), Num b, Num a, Ord b, Ord a) =>
              (a, b)

并启用FlexibleContexts:

Prelude> max (1, 2) 3

<interactive>:1:1: error:
    • No instance for (Num (Integer, Integer))
        arising from a use of ‘it’
    • In the first argument of ‘print’, namely ‘it’
      In a stmt of an interactive GHCi command: print it

这是a discussion

© www.soinside.com 2019 - 2024. All rights reserved.