10

Attualmente mi sto occupando di un codice Haskell che non ho scritto, ma di cui ho apportato delle modifiche. Dopo le mie modifiche, corro il programma e ottenere il seguente messaggio di errore:Posso usare OverlappingInstances per ottenere messaggi di errore più gradevoli?

Prelude.!!: index too large 

La chiamata a !! non è nel mio codice, quindi refactoring via è più lavoro che voglio fare, se posso evitarlo .

Quello che mi piacerebbe è quello di fare qualcosa di simile:

class PrintList a where 
    (!!) :: [a] -> Int -> a 

instance (Show a) => PrintList a where 
    l (!!) n = if n < (length l) 
      then (l Prelude.!! n) 
      else error ("Index " ++ show n ++ " out of bounds in " ++ show l) 

instance PrintList a where 
    (!!) = Prelude.!! 

vale a dire la funzione !! è definita per ogni possibile tipo di lista, ma si comporta in modo diverso ogni volta che un Visualizza istanza viene definito per il tipo di elemento.

In alternativa, un metodo tryShow :: a -> Maybe String farebbe anche il trucco.

C'è un modo per farlo? Posso forzare OverlappingInstances a utilizzare l'implementazione predefinita solo quando l'implementazione Show non si applica? Questo comportamento è garantito?

MODIFICA: punti bonus per chiunque riesca a ottenere l'errore anche per stampare un messaggio simile a una traccia stack!

risposta

8

Non è necessario casi si sovrappongono, basta usare il debugger GHC sul proprio (!!): sessione

{-# OPTIONS -Wall -O0 #-} 
module Debugger3 where 

import qualified Prelude as P 
import Prelude hiding ((!!)) 

(!!) :: [a] -> Int -> a 
xs !! n = 
    xs P.!! n -- line 9 

foo :: Int -> Int 
foo n = [0..n] !! 3 

bar :: Int -> Int 
bar n = foo (n-3) 

main :: IO() 
main = print (bar 4) 

GHCi:

> :l Debugger3 
[1 of 1] Compiling Debugger3  (Debugger3.hs, interpreted) 
Ok, modules loaded: Debugger3. 
*Debugger3> :break 9 
Breakpoint 1 activated at Debugger3.hs:9:4-18 
*Debugger3> :trace main 
Stopped at Debugger3.hs:9:4-18 
_result :: a = _ 
n :: Int = 3 
xs :: [a] = _ 
[Debugger3.hs:9:4-18] *Debugger3> :force xs 
xs = [0,1] 
[Debugger3.hs:9:4-18] *Debugger3> :history 
-1 : !! (Debugger3.hs:(8,1)-(9,18)) 
-2 : foo (Debugger3.hs:12:9-19) 
-3 : foo (Debugger3.hs:12:1-19) 
-4 : bar (Debugger3.hs:15:9-17) 
-5 : bar (Debugger3.hs:15:1-17) 
-6 : main (Debugger3.hs:18:15-19) 
-7 : main (Debugger3.hs:18:8-20) 
<end of history> 
[Debugger3.hs:9:4-18] *Debugger3> :back 
Logged breakpoint at Debugger3.hs:(8,1)-(9,18) 
_result :: a 
[-1: Debugger3.hs:(8,1)-(9,18)] *Debugger3> :back 
Logged breakpoint at Debugger3.hs:12:9-19 
_result :: Int 
n :: Int 
[-2: Debugger3.hs:12:9-19] *Debugger3> n 
1 
+0

Questo è stato eccellente, ed è sicuramente il "mondo reale" risposta. Ma mi piacerebbe comunque vedere se c'è un modo per ottenere il comportamento delle istanze di cui sto parlando. – jmite

Problemi correlati