haskell - online - ¿Para qué sirve la extensión FlexibleContexts? ¿Podría por favor explicarlo usando un ejemplo simple?
haskell core download (3)
Comúnmente se usa con la extensión MultiParamTypeClasses
, por ejemplo, al usar la biblioteca mtl
que podría escribir
doSomethingWithState :: MonadState MyState m => m ()
doSomethingWithState = do
current <- get
let something1 = computeSomething1 current
something2 = computeSomething2 current something1
put something2
Y de manera similar con MonadReader
y MonadWriter
, junto con otras clases de tipos similares. Sin FlexibleContexts
no puedes usar esta restricción.
(Tenga en cuenta que esta respuesta se basó en la de @DiegoNolan''s pero fue reescrita para usar una biblioteca existente que debería tener sentido para los lectores de LYAH).
Estaba tratando de entender lo que hace la extensión FlexibleContexts al buscar páginas web que lo expliquen a simples mortales (personas que han leído LYHFGG, como yo) pero no encontré ningún recurso de ese tipo.
Por lo tanto , pregunto a los expertos sobre el tema: ¿Alguien podría explicar qué hace esta extensión, por qué existe y dar uno o dos ejemplos simples de cómo y por qué se debe usar?
Además , si estoy leyendo el código de otra persona which usa esta extensión, ¿qué debo saber sobre la extensión para entender el código escrito con esta extensión?
He descubierto un uso para él aparte de los mencionados: da como resultado mensajes de error más claros de GHC. Por ejemplo, normalmente
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)
Y con FlexibleContexts habilitado:
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
Aquí hay una discusión .
Sin FlexibleContexts
todas las restricciones de clase de clase en las definiciones de funciones deben tener variables de tipo. Por ejemplo:
add :: Num a => a -> a
add = (+)
Donde a
es la variable de tipo. Con FlexibleContexts
habilitado puede tener cualquier tipo dentro de una clase de tipos.
intAdd :: Num Int => Int -> Int
intAdd = (+)
Este ejemplo es bastante artificial, pero es el más simple que se me ocurre. FlexibleContexts
generalmente solo se usa con MultiParamTypeClasses
. Aquí hay un ejemplo:
class Shower a b where
myShow :: a -> b
doSomething :: Shower a String => a -> String
doSomething = myShow
Aquí puedes ver que decimos que solo queremos un Shower a String
. Sin FlexibleContexts
String
tendría que ser una variable de tipo en lugar de un tipo concreto.