Pergunta

Costumo encontrar esse padrão no código Haskell:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

doSomething :: Foo -> Bar
doSomething = unsafePerformIO $ do
  opt <- readMVar options
  doSomething' where ...

Basicamente, possui-se um registro de opções ou algo semelhante, que é inicialmente definido no início do programa.Como o programador é preguiçoso, ele não quer carregar o options grave todo o programa.Ele define um MVar mantê-lo - definido por um uso feio de unsafePerformIO.O programador garante que o estado seja definido apenas uma vez e antes de qualquer operação ser realizada.Agora cada parte do programa tem que usar unsafePerformIO novamente, apenas para extrair as opções.

Na minha opinião, tal variável é considerada pragmaticamente puro (não me bata).Existe uma biblioteca que abstrai esse conceito e garante que a variável seja definida apenas uma vez, ou seja,que nenhuma chamada é feita antes dessa inicialização e que não é necessário escrever unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName

Foi útil?

Solução

Se você estiver usando MVar para manter configurações ou algo semelhante, por que não tenta o leitor mônada?

foo :: ReaderT OptionRecord IO ()
foo = do
    options <- ask
    fireMissiles

main = runReaderT foo (OptionRecord "foo")

(E leitor normal se você não precisar de IO: P)

Outras dicas

Aqueles que trocavam transparência referencial essencial por um pouco de conveniência temporária não merecem pureza nem conveniência.

Esta é uma má ideia.O código que você está encontrando é um código incorreto.*

Não há como encerrar totalmente esse padrão com segurança, porque não é um padrão seguro.Não faça isso no seu código.Não procure uma maneira segura de fazer isso.Não existe uma maneira segura de fazer isso.Coloque o unsafePerformIO deite-se no chão, lentamente, e afaste-se do console...

*Existem razões legítimas para as pessoas usarem MVars de nível superior, mas essas razões têm a ver com ligações a código estrangeiro na maior parte, ou algumas outras coisas onde a alternativa é muito confusa.Nesses casos, pelo que eu sei, porém, os MVars de nível superior são não acessado por trás unsafePerformIO.

Use parâmetros implícitos.Eles são um pouco menos pesados ​​do que fazer com que todas as funções tenham Reader ou ReaderT em seu tipo.Você precisa alterar as assinaturas de tipo de suas funções, mas acho que tal alteração pode ser programada.(Seria um ótimo recurso para um IDE Haskell.)

Há uma razão importante para não usar esse padrão.Pelo que eu sei, em

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

Haskell não dá garantias de que options será avaliado apenas uma vez.Desde o resultado de option é um valor puro, pode ser memorizado e reutilizado, mas também pode ser recalculado para cada chamada (ou seja,embutido) e o significado do programa não deve mudar (ao contrário do seu caso).

Se você ainda decidir usar esse padrão, certifique-se de adicionar {-# NOINLINE options #-}, caso contrário, ele poderá ficar embutido e seu programa falhará!(E com isso estamos saindo das garantias dadas pela linguagem e pelo sistema de tipos e contando apenas com a implementação de um compilador específico.)

Este tópico foi amplamente discutido e as possíveis soluções estão bem resumidas no Haskell Wiki em Estado mutável de nível superior.Atualmente não é possível abstrair esse padrão com segurança sem algum suporte adicional do compilador.

Costumo encontrar esse padrão no código Haskell:

Leia código diferente.

Como o programador é preguiçoso, ele não quer carregar o registro das opções por todo o programa.Ele define um MVar para mantê-lo - definido por um uso feio de unsafePerformIO.O programador garante que o estado seja definido apenas uma vez e antes de qualquer operação ser realizada.Agora cada parte do programa deve usar unsafePerformIO novamente, apenas para extrair as opções.

Parece literalmente exatamente o que a mônada leitora realiza, exceto que a mônada leitora faz isso de maneira segura.Em vez de acomodar sua própria preguiça, apenas escreva um código realmente bom.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top