haskell - Cómo relacionarse con el tipo de contexto externo
types functional-programming (2)
Esto es posible con la extensión ScopedTypeVariables . Necesita usar reglas explícitas para poner las variables de tipo dentro del alcance.
blah :: forall a b. a -> b -> a
blah x y = ble x where
ble :: b -> b
ble x = x
Intentar cargar esta definición con ScopedTypeVariables habilitado da:
foo.hs:2:16:
Couldn''t match type `a'' with `b''
`a'' is a rigid type variable bound by
the type signature for blah :: a -> b -> a at foo.hs:2:1
`b'' is a rigid type variable bound by
the type signature for blah :: a -> b -> a at foo.hs:2:1
In the first argument of `ble'', namely `x''
In the expression: ble x
In an equation for `blah'':
blah x y
= ble x
where
ble :: b -> b
ble x = x
Puede decir que GHC interpreta las dos b
s como del mismo tipo porque el error dice que a
y b
están vinculados en la misma línea.
Consideremos el siguiente fragmento de código:
blah :: a -> b -> a
blah x y = ble x where
ble :: b -> b
ble x = x
Esto compila bien bajo GHC, lo que esencialmente significa que b
de la 3ra línea es algo diferente de b
de la primera línea.
Mi pregunta es simple: ¿hay alguna forma de relacionarse de algún modo en la declaración de tipo de ble
con un tipo utilizado en un contexto externo, es decir, la declaración de tipo de blah
?
Obviamente, esto es solo un ejemplo y no un caso de uso del mundo real para las declaraciones de tipo.
Si no desea utilizar ScopedTypeVariables, puede utilizar la función good ole fashion asTypeOf
.
-- defined in Prelude
asTypeOf :: a -> a -> a
x `asTypeOf` y = x
blah :: a -> b -> a
blah x y = ble x where
ble x = x `asTypeOf` y
Por supuesto, esto no se compilará debido al error de tipo.
Actualizar:
Me gustaría señalar que a veces puede ser un poco astuto hacer lo que quiera con asTypeOf
. Tome el siguiente ejemplo que asTypeOf
usa asTypeOf
porque no quiero pensar en un caso que realmente necesite asTypeOf
. Soluciones similares funcionarían igual para casos del mundo real.
foo :: Bounded a => Maybe a -> a
foo m = x
where
x = maxBound -- Q: how do I make (x :: a) when given (Maybe a)?
_ = Just x `asTypeof` m -- A: witchcraft!