Questo non funziona, ma ho pensato che era abbastanza interessante da condividere in ogni caso:
{-#LANGUAGE GADTs #-}
data Poly a where
Poly :: [b] -> Poly [b]
Ora abbiamo un tipo Poly che è parametrizzata su a
, ma efficace a
deve essere una lista:
~% ghci Poly.hs
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help
Loading package base ... linking ... done.
[1 of 1] Compiling Main (Poly.hs, interpreted)
Ok, modules loaded: Main.
*Main> :k Poly
Poly :: * -> *
*Main> :t Poly
Poly :: [b] -> Poly [b]
*Main> case Poly [1,2,3] of _ -> 0
0
*Main> case Poly 4 of _ -> 0
<interactive>:1:10:
No instance for (Num [b])
arising from the literal `4' at <interactive>:1:10
Possible fix: add an instance declaration for (Num [b])
In the first argument of `Poly', namely `4'
In the scrutinee of a case expression: Poly 4
In the expression: case Poly 4 of _ -> 0
*Main> case Poly True of _ -> 0
<interactive>:1:10:
Couldn't match expected type `[b]' against inferred type `Bool'
In the first argument of `Poly', namely `True'
In the scrutinee of a case expression: Poly True
In the expression: case Poly True of _ -> 0
Ora possiamo provare a scrivere un'istanza di Functor
per questo tipo:
instance Functor Poly where
fmap f (Poly x) = Poly (f x)
Couldn't match expected type `[b1]' against inferred type `b2'
`b2' is a rigid type variable bound by
the type signature for `fmap' at <no location info>
In the first argument of `Poly', namely `(f x)'
In the expression: Poly (f x)
In the definition of `fmap': fmap f (Poly x) = Poly (f x)
Non funzionerà. È interessante notare, non possiamo ancora veramente scrivere myMap
:
polymap f (Poly x) = Poly (f x)
Se proviamo questo otteniamo
GADT pattern match in non-rigid context for `Poly'
Tell GHC HQ if you'd like this to unify the context
In the pattern: Poly x
In the definition of `polymap': polymap f (Poly x) = Poly (f x)
Naturalmente possiamo risolvere il problema con un tipo di annotazione:
polymap :: ([a] -> [b]) -> Poly [a] -> Poly [b]
Ma senza di esso, è un problema simile a quello che aveva fmap. Functor semplicemente non ha da nessuna parte fuori questo contesto extra di "Prometto sempre di usare le liste", e in effetti non può davvero. Ad esempio, puoi sempre dire undefined :: Poly Int
. In breve, non penso che ci sia davvero un idioma che potrebbe esprimere questo (in realtà, qualcuno probabilmente verrà con abbastanza magia ghc per farlo). Certamente non uno esistente.
Cosa vorresti fare per fmap (prendere 3) polinomio? Non ha alcun senso per me. - 'polinomio' è semplicemente un' polinomio :: Poly CoeffType' 'polinomiale = Poly [a₁, a₂ ..]'? – leftaroundabout
@leftaroundabout: ho fornito un codice di esempio. – Xodarap
Dato che questa non è realmente un'operazione canonica (come dovrebbe sapere che la classe di caratteri è una lista e non ad esempio una matrice), non ne farei alcuna istanza. Inoltre, non lo chiamerei "some-'map'", ma piuttosto "coeffsTransform" o qualcosa del genere. – leftaroundabout