Haskell: Posso usare una clausola in cui, dopo un blocco con gli operatori bind (>> =)?

StackOverflow https://stackoverflow.com/questions/1156954

  •  18-09-2019
  •  | 
  •  

Domanda

Ho una domanda molto semplice. Mi piacerebbe usare una clausola where dopo un blocco di codice che utilizza gli operatori legano ma ottengo un errore di compilazione.

Ecco un semplice esempio:

main =
    putStrLn "where clause test:" >>
    return [1..10] >>= \list ->
    print list'
        where list' = reverse list -- test1.hs:5:28: Not in scope: `list'

posso usare una clausola let per la lista' come in

main =
    putStrLn "where clause test:" >>
    return [1..10] >>= \list ->
    let list' = reverse list -- works of course
    in print list'

ma mi piacerebbe davvero se potevo usare una clausola where ...

Ho provato anche con la notazione non

main = do
    putStrLn "where clause test:"
    list <- return [1..10]
    print list'
        where list' = reverse list --test3.hs:5:30: Not in scope: `list'

Lo stesso problema. Posso usare una clausola where in queste circostanze?

È stato utile?

Soluzione

Come spiega ephemient, non è possibile utilizzare where Clausole il modo di fare.

L'errore si verifica perché in questo codice:

main =
  return [1..10] >>= \list ->
  print list'
    where
      list' = reverse list

Il where-clausola è attaccato alla funzione principale.

Ecco che la stessa funzione con più parentesi:

main = return [1..10] >>= (\list -> print list')
  where
    list' = reverse list

Credo che la sua abbastanza ovvio il motivo per cui si ottiene l'errore "out of scope": l'associazione per list è profondo l'espressione main, non qualcosa la clausola where può raggiungere

.

Quello che faccio di solito in questa situazione (e sono stato morso dalla stessa cosa un mucchio di volte). Ho semplicemente introdurre una funzione e passare il list come argomento.

main = do
  list <- return [1..10]
  let list' = f list
  print list'
  where
    f list = reverse list -- Consider renaming list,
                          -- or writing in point-free style

Naturalmente, immagino il codice vero e proprio nella funzione f è molto più che appena reverse ed è per questo che si desidera all'interno di una clausola di where, invece di un legame let linea. Se il codice all'interno della funzione f è molto piccolo, avevo appena scrivo all'interno vincolante il let, e non vorrei passare attraverso il sovraccarico di introdurre una nuova funzione.

Altri suggerimenti

Per quanto posso dire, la clausola where viene utilizzato solo in attacchi locali . La parte interna di un >> (=) dichiarazione vincolante non è un locale vincolanti (due diversi tipi di attacchi in quella frase).

Confronto con questo:

main = f [1..10]

f list =
    putStrLn "where clause test:" >> print list'
        where list' = reverse list

Si potrebbe desiderare di fare riferimento alla Haskell 98 sintassi rapporto - non sicuro di quanto l'aiuto sarebbe stato.

Se mi sbaglio, qualcuno certamente mi corregga, ma sono abbastanza sicuro che non è possibile utilizzare una clausola in cui a tutti in stile che hai mostrato in precedenza. list non sarà mai portata ad una clausola in cui a meno che non si tratta di un parametro alla funzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top