Moving Average Haskell


Embora a pureza Haskells venha com um monte de benefícios, isso nos faz enfrentar alguns problemas de maneira diferente do que faríamos em linguagens impuras. Devido à transparência referencial, um valor é tão bom quanto outro em Haskell se ele representa a mesma coisa. Então, se tivermos uma árvore cheia de cinco (cinco vezes, talvez) e queremos mudar uma delas para uma seis, temos que ter alguma maneira de saber exatamente quais as cinco da nossa árvore que queremos mudar. Nós temos que saber onde está em nossa árvore. Em linguas impuras, podemos simplesmente notar onde em nossa memória os cinco estão localizados e mudam isso. Mas em Haskell, um cinco é tão bom quanto outro, então não podemos discriminar com base em onde estamos em nossa memória. Nós também não podemos realmente mudar nada quando dizemos que mudamos uma árvore, queremos dizer que nós levamos uma árvore e devolvemos uma nova que é semelhante à árvore original, mas ligeiramente diferente. Uma coisa que podemos fazer é lembrar um caminho da raiz da árvore para o elemento que queremos mudar. Podemos dizer, pegue esta árvore, vá para a esquerda, vá para a direita e depois saia de novo e mude o elemento que está lá. Enquanto isto funciona, pode ser ineficiente. Se quisermos mudar mais tarde um elemento próximo ao elemento que mudamos anteriormente, devemos caminhar todo o caminho da raiz da árvore para o nosso elemento novamente. Neste capítulo, veja como podemos tomar alguma estrutura de dados e focar Uma parte dela de uma forma que facilita a mudança de seus elementos e a sua caminhada é eficiente. Nice Como andar Como aprendemos na classe de biologia, existem muitos tipos diferentes de árvores, então vamos escolher uma semente que usaremos para plantar a nossa. Aqui está: Então nossa árvore está vazia ou é um nó que tem um elemento e duas sub-árvores. É um bom exemplo de tal árvore, que eu dou a você, o leitor, de graça. E heres esta árvore representada graficamente: Observe que W na árvore lá. Digamos que queremos transformá-lo em um P. Como iremos fazer Que Bem, uma maneira seria padronizar a partida em nossa árvore até encontrarmos o elemento que está localizado primeiro indo para a direita e depois para a esquerda e mudando o referido elemento. Heres o código para isso: Yuck Não só isso é bastante feio, também é um pouco confuso. O que acontece aqui Bem, nós padronamos a partida em nossa árvore e nomeamos seu elemento raiz x (isso se torna o P na raiz) e sua sub-árvore esquerda l. Em vez de dar um nome à sua sub-árvore direita, nós ainda padronizamos a correspondência. Continuamos este padrão de correspondência até chegarmos à sub-árvore cuja raiz é o nosso W. Uma vez que fizemos isso, reconstruímos a árvore, apenas a sub-árvore que continha o W em sua raiz agora tem um P. Existe uma maneira melhor De fazer isso. Que tal nós fazemos nossa função tomar uma árvore junto com uma lista de direções. As direções serão L ou R. representando esquerda e direita, respectivamente, e bem mudar o elemento que chegamos se seguimos as instruções fornecidas. Aqui está: Se o primeiro elemento na nossa lista de direções é L. nós construímos uma nova árvore que é como a árvore antiga, somente sua sub-árvore esquerda tem um elemento alterado para P. Quando chamamos recursivamente changeToP. Nós damos apenas a cola da lista de direções, porque já vimos à esquerda. Fazemos o mesmo no caso de um R. Se a lista de direções estiver vazia, isso significa que estavam em nosso destino, então devolvemos uma árvore que é como a fornecida, apenas ela tem P como seu elemento raiz. Para evitar a impressão de toda a árvore, vamos fazer uma função que leva uma lista de direções e nos diz qual é o elemento no destino: esta função é bastante parecida com o ChangeToP. Apenas em vez de lembrar coisas ao longo do caminho e reconstruir a árvore, ela ignora tudo, exceto o seu destino. Aqui mudamos o W para um P e veremos se a mudança na nossa nova árvore se encaixa: Nice, isso parece funcionar. Nessas funções, a lista de direções atua como uma espécie de foco. Porque identifica uma sub-árvore exata da nossa árvore. Uma lista direcionada de R enfoca a sub-árvore que está à direita da raiz, por exemplo. Uma lista de direção vazia enfoca a árvore principal em si. Embora esta técnica possa parecer legal, pode ser bastante ineficiente, especialmente se quisermos mudar repetidamente elementos. Digamos que temos uma árvore realmente enorme e uma lista de direção longa que aponta para algum elemento no final da árvore. Usamos a lista de direção para caminhar ao longo da árvore e mudar um elemento na parte inferior. Se quisermos mudar outro elemento que esteja próximo ao elemento que acabamos de mudar, devemos começar a partir da raiz da árvore e caminhar até o fundo novamente. O que é um arrastar. Na próxima seção, encontre uma maneira melhor de se concentrar em uma sub-árvore, que nos permita mudar eficientemente o foco para sub-árvores próximas. Uma trilha de migalhas de pão Ok, então, para se concentrar em uma sub-árvore, queremos algo melhor do que apenas uma lista de direções que sempre seguimos da raiz da nossa árvore. Isso ajudaria se começássemos na raiz da árvore e mova-se à esquerda ou à direita um passo de cada vez, e deixemos o pão ralado, isto é, quando vamos para a esquerda, lembramos que fomos para a esquerda e quando nós vamos direto, lembramos Que fomos direto. Claro, podemos tentar isso. Para representar nossas migalhas de pão, bem, também use uma lista de Direção (que é L ou R), apenas em vez de chamar Direção. Bem, chame-o de migalhas de pão. Porque nossas direções agora serão revertidas uma vez que as deixaram enquanto descemos nossa árvore: Heres uma função que leva uma árvore e algumas migalhas de pão e se move para a sub-árvore esquerda, enquanto adiciona L na cabeça da lista que representa o nosso pão ralado: Ignoramos o elemento na sub-árvore raiz e direita e apenas devolvemos a sub-árvore esquerda, juntamente com as migalhas de pão antigas com L como cabeça. Sua função é ir corretamente: funciona da mesma maneira. Permite usar essas funções para tirar nosso FreeTree e ir para a direita e depois para a esquerda: Ok, então agora temos uma árvore que tem W em sua raiz e C na raiz de sua sub-árvore esquerda e R na raiz de sua sub - árvore. As migalhas de pão são L, R. Porque primeiro fomos à direita e depois à esquerda. Para fazer uma caminhada ao longo da nossa árvore mais clara, podemos usar a função -: que definimos de forma semelhante: o que nos permite aplicar funções aos valores, primeiro escrevendo o valor, depois escrevendo a -: e depois a função. Então, em vez de goRight (FreeTree,). Podemos escrever (freeTree,) -: goRight. Usando isso, podemos reescrever o acima para que seja mais evidente que foram primeiro indo para a direita e depois para a esquerda: Voltando o backup Se, agora, queremos voltar a nossa árvore. De nossa barraca de pão, sabemos que a árvore atual é a sub-região esquerda - tree de seu pai e que é a sub-árvore certa de seu pai, mas é isso. Eles não nos dizem o suficiente sobre o pai da sub-árvore atual para que possamos subir na árvore. Parece que, além da direção que tomamos, uma única migalha de pão também deve conter todos os outros dados que precisamos voltar a fazer. Nesse caso, esse é o elemento na árvore-mãe, juntamente com sua sub-árvore direita. Em geral, um único breadcrumb deve conter todos os dados necessários para reconstruir o nó pai. Então, deve ter a informação de todos os caminhos que não tomamos e também deve saber a direção que fizemos, mas não deve conter a sub-árvore que atualmente estava focada. Isso porque nós já possuímos essa sub-árvore no primeiro componente da tupla, então, se também tivéssemos isso na trituração, mande informações duplicadas. Vamos modificar nossas migalhas de pão para que eles também contenham informações sobre tudo o que anteriormente ignoramos ao mover para a esquerda e para a direita. Em vez de Direção. Bem, faça um novo tipo de dados: agora, em vez de apenas L., temos um LeftCrumb que também contém o elemento no nó de onde nos mudamos e a árvore certa que não visitamos. Em vez de R. temos RightCrumb. Que contém o elemento no nó de onde nos mudamos e a árvore esquerda que não visitamos. Essas migalhas de mapas agora contêm todos os dados necessários para recriar a árvore que passamos. Então, ao invés de apenas ser migalhas de pão normais, elas são agora mais como disquetes que nós deixamos enquanto vamos, porque eles contêm muito mais informações do que apenas a direção que tomamos. Em essência, cada migalha de pão é agora como um nó de árvore com um buraco nela. Quando nos movemos mais fundo para uma árvore, o breadcrumb carrega toda a informação que o nó que nos afastamos de transportar, exceto a sub-árvore na qual escolhemos focar. Também deve notar onde o buraco é. No caso de um LeftCrumb. Nós sabemos que nos mudamos para a esquerda, então a sub-árvore que está faltando é a esquerda. Permita também alterar o nosso sinônimo de tipo Breadcrumbs para refletir isso: Em seguida, temos que modificar as funções goLeft e goRight para armazenar informações sobre os caminhos que não tomamos no nosso breadcrumbs, em vez de ignorar essas informações como antes. Heres goLeft. Você pode ver que é muito semelhante ao nosso goLeft anterior. Apenas em vez de adicionar um L ao cabeçalho da nossa lista de migalhas de pão, adicionamos um LeftCrumb para significar que fomos para a esquerda e nós equiparamos nosso LeftCrumb com o elemento no nó de onde nos mudamos (isto é o x) e o submarino direito - Por favor, escolhemos não visitar. Observe que esta função assume que a árvore atual que está em foco não está vazia. Uma árvore vazia não tem sub-árvores, então, se tentarmos ir para a esquerda de uma árvore vazia, um erro ocorrerá porque o padrão combinado no Nó não será bem-sucedido e não há padrão que cuide de Vazio. O goRight é semelhante: anteriormente, poderíamos ir para a esquerda e para a direita. O que conseguimos agora é a capacidade de voltar atrás lembrando coisas sobre os nós pai e os caminhos que não visitamos. Heres a função goUp: focalizamos a árvore t e verificamos qual é o último Crumb. Se for um LeftCrumb. Então, construímos uma nova árvore onde nossa árvore t é a sub-árvore esquerda e usamos as informações sobre a sub-árvore direita que não visitamos e o elemento para preencher o resto do Nó. Porque nos mudamos de novo por assim dizer e pegamos a última fila para recriar com ele a árvore-mãe, a nova lista de migalhas de pão não o contém. Observe que esta função causa um erro se já estivesse no topo de uma árvore e queremos subir de movimento. Mais tarde, use o talvez Mônada para representar possíveis falhas ao mover o foco. Com um par de Tree a e Breadcrumbs a. Nós temos toda a informação para reconstruir toda a árvore e também nos concentramos em uma sub-árvore. Este esquema também nos permite avançar facilmente, para a esquerda e para a direita. Esse par que contém uma parte focada de uma estrutura de dados e seus arredores é chamado de zíper, porque mover nosso foco para cima e para baixo a estrutura de dados se assemelha à operação de um zíper em uma calça regular. Então, é legal fazer um tipo de sinônimo como tal: prefiro nomear o tipo de sinônimo de foco, porque isso torna mais claro que se concentraram em uma parte de uma estrutura de dados, mas o termo zíper é mais amplamente utilizado para descrever tal configuração, tão bem Fique com Zipper. Manipulando árvores em foco Agora que podemos mover-se para cima e para baixo, vamos fazer uma função que modifica o elemento na raiz da sub-árvore na qual o zíper está focado: Se estivesse se concentrando em um nó, modificamos seu elemento raiz com o Função f. Se estivesse se concentrando em uma árvore vazia, deixamos como está. Agora podemos começar com uma árvore, mover para qualquer lugar que desejamos e modificar um elemento, tudo ao manter o foco nesse elemento para que possamos facilmente avançar para cima ou para baixo. Um exemplo: vamos para a esquerda, depois para a direita e, em seguida, modificamos o elemento raiz, substituindo-o por um P. Isso se lê ainda melhor se usarmos -. Podemos então avançar se quisermos e substituir um elemento por um misterioso X. Ou se o escrevemos com -. Mover-se é fácil porque as migalhas de pão que deixamos formam a parte da estrutura de dados que não estava focada, mas é invertida, como girar uma meia de dentro para fora. É por isso que, quando queremos subir, não temos que começar da raiz e diminuímos, mas acabamos de tomar o topo da nossa árvore invertida, desvinculando assim uma parte dela e adicionando-a ao nosso foco. Cada nó tem duas sub-árvores, mesmo que essas sub-árvores sejam árvores vazias. Então, se estivesse se concentrando em uma sub-árvore vazia, uma coisa que podemos fazer é substituí-la por uma sub-árvore não vazia, anexando uma árvore a um nó da folha. O código para isso é simples: pegamos uma árvore e um zíper e devolvemos um novo zíper que tem o foco substituído pela árvore fornecida. Não só podemos estender as árvores desse modo, substituindo sub-árvores vazias por novas árvores, também podemos substituir sub-árvores existentes. Permite anexar uma árvore à extrema esquerda do nosso FreeTree. NewFocus agora está focado na árvore que acabamos de anexar e o resto da árvore está invertida no pão ralado. Se usássemos goUp para caminhar até o topo da árvore, seria a mesma árvore que FreeTree, mas com um Z adicional na sua extrema esquerda. Eu vou direto para o topo, oh sim, até onde o ar está fresco e limpo Fazendo uma função que caminha até o topo da árvore, independentemente do que estava focado, é realmente fácil. Aqui é: se a nossa trilha de panelas de pão reforçada estiver vazia, isso significa que já estavam na raiz da nossa árvore, então nós apenas retornamos o foco atual. Caso contrário, vamos para obter o foco do nó pai e, em seguida, aplicar recursivamente topMost para isso. Então, agora podemos caminhar pela nossa árvore, indo para a esquerda e para a direita e para cima, aplicando modificar e anexar enquanto seguimos e então, quando terminamos com nossas modificações, usamos topMost para focar a raiz da nossa árvore e ver as mudanças que temos Feito na perspectiva adequada. Centrando-se em listas Zippers pode ser usado com praticamente qualquer estrutura de dados, então não é surpresa que eles possam ser usados ​​para se concentrar em sub-listas de listas. Afinal, as listas são muito parecidas com árvores, apenas onde um nó em uma árvore tem um elemento (ou não) e várias sub-árvores, um nó em uma lista tem um elemento e apenas uma única sub-lista. Quando implementamos nossas próprias listas. Nós definimos nosso tipo de dados de modo a: Contraste isso com a nossa definição de nossa árvore binária e é fácil ver como as listas podem ser vistas como árvores em que cada nó possui apenas uma sub-árvore. Uma lista como 1,2,3 pode ser escrita como 1: 2: 3 :. Consiste na cabeça da lista, que é 1 e, em seguida, as listas de cauda, ​​que é 2: 3 :. Por sua vez, 2: 3: também tem uma cabeça, que é 2 e uma cauda, ​​que é 3 :. Com 3 :. O 3 é a cabeça e a cauda é a lista vazia. Vamos criar um zíper para listas. Para alterar o foco nas sub-listas de uma lista, movemos para frente ou para trás (enquanto que com as árvores nos movemos para cima ou para a esquerda ou para a direita). A parte focada será uma sub-árvore e, juntamente com isso, deixará migalhas de pão à medida que avançarmos. Agora, o que um único breadcrumb para uma lista consistiria. Quando estávamos lidando com árvores binárias, dissemos que um breadcrumb tem que manter o elemento na raiz do nó pai, juntamente com todas as sub-árvores que não escolhemos. Também tinha que lembrar se fomos para a esquerda ou para a direita. Então, teve que ter todas as informações que um nó tem, exceto a sub-árvore na qual escolhemos focar. As listas são mais simples do que as árvores, então não precisamos lembrar se fomos para a esquerda ou para a direita, porque há apenas uma maneira de ir mais fundo em uma lista. Porque há apenas uma sub-árvore para cada nó, não precisamos lembrar os caminhos que não tomamos também. Parece que tudo o que temos que lembrar é o elemento anterior. Se tivermos uma lista como 3,4,5 e sabemos que o elemento anterior era 2. podemos voltar atrás apenas colocando esse elemento à nossa lista, recebendo 2,3,4,5. Como uma única migalha de pão aqui é apenas o elemento, não precisamos colocá-lo dentro de um tipo de dados, como fizemos quando fizemos o tipo de dados Crumb para zíperes de árvores: a primeira lista representa a lista que estava focada e a segunda lista É a lista de migalhas de pão. Permite criar funções que avançam e voltam para as listas: quando avançamos, nos concentramos na cauda da lista atual e deixamos o elemento principal como uma navegação. Quando nos movemos para trás, tomamos a última fila e colocamos no início da lista. Aqui estão estas duas funções em ação: vemos que as migalhas de barras no caso de listas não são mais que uma parte reversa da nossa lista. O elemento de que nos afastamos sempre entra na cabeça das migalhas de pão, por isso é fácil voltar atrás, tirando esse elemento da cabeça das migalhas de pão e tornando-se a cabeça do nosso foco. Isso também torna mais fácil ver por que chamamos isso de zíper, porque isso realmente se parece com o controle deslizante de um zíper movendo-se para cima e para baixo. Se você estivesse fazendo um editor de texto, você poderia usar uma lista de strings para representar as linhas de texto que estão atualmente abertas e, em seguida, você poderia usar um zíper para saber em que linha o cursor está focado atualmente. Ao usar um zíper, também seria mais fácil inserir novas linhas em qualquer parte do texto ou excluir as existentes. Um sistema de arquivos muito simples Agora que sabemos como funcionam os zíperes, usamos árvores para representar um sistema de arquivos muito simples e, em seguida, crie um zíper para esse sistema de arquivos, o que nos permitirá mover-se entre as pastas, como costumamos fazer quando pulamos Nosso sistema de arquivos. Se tomarmos uma visão simplista do sistema de arquivos hierárquico médio, vemos que é composto principalmente de arquivos e pastas. Os arquivos são unidades de dados e vêm com um nome, enquanto as pastas são usadas para organizar esses arquivos e podem conter arquivos ou outras pastas. Então, digamos que um item em um sistema de arquivos é um arquivo, que vem com um nome e alguns dados, ou uma pasta, que tem um nome e, em seguida, um monte de itens que são arquivos ou pastas. É um tipo de dados para este e alguns tipos de sinônimos, então sabemos o que é: um arquivo vem com duas strings, que representam seu nome e os dados que detém. Uma pasta vem com uma string que é o nome e uma lista de itens. Se essa lista estiver vazia, então temos uma pasta vazia. Heres uma pasta com alguns arquivos e subpastas: isso é realmente o que meu disco contém agora. Um zíper para o nosso sistema de arquivos Agora que temos um sistema de arquivos, tudo o que precisamos é um zíper para que possamos compactar e ampliar o zoom e adicionar, modificar e remover arquivos, bem como pastas. Como com árvores binárias e listas, iriam deixar migalhas de pão que contêm informações sobre todas as coisas que escolhemos para não visitar. Como dissemos, um único breadcrumb deve ser um pouco como um nó, apenas ele deve conter tudo, exceto a sub-árvore que estava focando atualmente. Também deve notar onde o buraco é para que, uma vez que nos movamos de volta, podemos conectar nosso foco anterior ao buraco. Nesse caso, um breadcrumb deve ser como uma pasta, apenas deve estar faltando a pasta que escolhemos atualmente. Por que não gostar de um arquivo, você perguntará Bem, porque uma vez se concentraram em um arquivo, não podemos avançar mais profundamente no sistema de arquivos, então não faz sentido deixar um breadcrumb que diz que nós viermos de um arquivo. Um arquivo é como uma árvore vazia. Se estivesse concentrando-se na raiz da pasta e então nos concentramos no arquivo dijonpoupon. doc. O que deve fazer com a navegação que deixamos pareça Bem, ele deve conter o nome da sua pasta pai, juntamente com os itens que vieram antes do arquivo que estava focado e os itens que o seguiam. Então, tudo o que precisamos é um Nome e duas listas de itens. Ao manter listas separadas para os itens que vieram antes do item que estava focando e para os itens que os acompanham, sabemos exatamente onde colocá-lo uma vez que nos movemos de volta. Então, assim, sabemos onde está o buraco. É o nosso tipo de navegação para o sistema de arquivos: e heres um tipo de sinônimo para o nosso zíper: voltar a hierarquia é muito simples. Nós apenas tomamos a última fila de navegação e reunimos um novo foco do foco atual e da navegação. Assim como: porque o nosso processo migratório sabia qual era o nome das pastas pai, bem como os itens que vieram antes do nosso item focado na pasta (thats ls) e aqueles que vieram depois (thats rs), mover-se foi fácil. Como se aprofundar no sistema de arquivos Se estivesse na raiz e queremos nos concentrar em dijonpoupon. doc. A rolagem que deixamos vai incluir o nome do raiz juntamente com os itens que precedem dijonpoupon. doc e os que o seguem. Heres uma função que, dada um nome, se concentra em um arquivo de pasta que está localizado na pasta focada atual: fsTo leva um Nome e um FSZipper e retorna um novo FSZipper que se concentra no arquivo com o nome. Esse arquivo deve estar na atual pasta focada. Esta função não procura em todo o lugar, apenas olha para a pasta atual. Primeiro, usamos uma interrupção para quebrar a lista de itens em uma pasta para aqueles que precedem o arquivo que estava procurando e aqueles que vieram depois dele. Se você se lembrar, o break toma um predicado e uma lista e retorna um par de listas. A primeira lista no par possui itens para os quais o predicado retorna False. Então, uma vez que o predicado retorna True para um item, ele coloca esse item e o resto da lista no segundo item do par. Criamos uma função auxiliar chamada nomeIs que leva um nome e um item do sistema de arquivos e retorna True se os nomes correspondem. Então, agora, ls é uma lista que contém os itens que precedem o item que estava procurando, o item é esse mesmo item e rs é a lista de itens que vem depois dele em sua pasta. Agora que temos isso, nós apenas apresentamos o item que obtivemos da ruptura como foco e criamos uma navegação que possui todos os dados de que precisa. Note que, se o nome procurava na pasta, o item de padrão: rs tentará combinar em uma lista vazia e, assim, obterá um erro. Além disso, se o nosso foco atual não é uma pasta, mas um arquivo, também recebemos um erro e o programa falha. Agora podemos mover para cima e para baixo nosso sistema de arquivos. Vamos começar na raiz e caminhar até o arquivo skullman (assustador).bmp. NewFocus agora é um zíper que está focado no arquivo. bmp skullman (assustador). Permite obter o primeiro componente do zíper (o foco em si) e veja se isso é realmente verdadeiro: vamos mover para cima e, em seguida, concentre-se no arquivo vizinho watermelonsmash. gif. Manipulando nosso sistema de arquivos Agora que sabemos como navegar no nosso sistema de arquivos, manipulá-lo é fácil. Heres uma função que renomeia o arquivo ou pasta atualmente focado: agora podemos renomear nossa pasta de fotos para cspi. Descimos para a pasta pics, renomeamos e depois nos movemos de volta. Como sobre uma função que faz um novo item na pasta atual? Veja: Fácil como torta. Tenha em atenção que isso iria falhar se tentássemos adicionar um item, mas não focarmos uma pasta, mas nos focamos em um arquivo. Permite adicionar um arquivo à nossa pasta de fotos e, em seguida, voltar para a raiz: o que é realmente legal sobre tudo isso é que, quando modificamos nosso sistema de arquivos, ele realmente não o modifica, mas retorna um sistema de arquivos totalmente novo. Dessa forma, temos acesso ao nosso antigo sistema de arquivos (neste caso, myDisk), bem como o novo (o primeiro componente do newFocus). Assim, usando zíperes, obtemos o controle de versão gratuitamente, o que significa que sempre podemos nos referir a versões antigas de estruturas de dados, mesmo depois de mudá-las, por assim dizer. Isso não é exclusivo para zíperes, mas é uma propriedade da Haskell porque suas estruturas de dados são imutáveis. Com os zíperes no entanto, nós conseguimos a capacidade de caminhar facilmente e eficientemente em torno de nossas estruturas de dados, então a persistência das estruturas de dados Haskells realmente começa a brilhar. Assista seu passo Até agora, ao caminhar através de nossas estruturas de dados, se fossem árvores binárias, listas ou sistemas de arquivos, realmente não nos importamos se dermos um passo demais e caiu. Por exemplo, nossa função goLeft tira um zíper de uma árvore binária e move o foco para a sua sub-árvore esquerda: Mas e se a árvore estivesse saindo, é uma árvore vazia. E se não for um Nó. Mas um vazio. Nesse caso, wed tenha um erro de tempo de execução porque a correspondência do padrão falharia e não fizemos nenhum padrão para lidar com uma árvore vazia, que não possui sub-árvores. Até agora, nós apenas assumimos que o wed nunca tenta se concentrar na sub-árvore esquerda de uma árvore vazia, pois sua sub-árvore esquerda não existe. Mas ir para a sub-árvore esquerda de uma árvore vazia não faz muito sentido, e até agora simplesmente ignoramos isso. E se nós já estivéssemos na raiz de alguma árvore e não tivéssemos panquecas, mas ainda tentávamos subir. O mesmo aconteceria. Parece que, ao usar zíperes, qualquer passo poderia ser a nossa última (música sinalizada). Em outras palavras, qualquer movimento pode resultar em um sucesso, mas também pode resultar em uma falha. Isso lembra algo, é claro. Mônadas. Mais especificamente, a talvez Mônada que adiciona um contexto de possível falha em valores normais. Então, use a talvez Mônada para adicionar um contexto de possível falha em nossos movimentos. Levaríamos as funções que funcionam no zíper de árvore binário e as transformaríamos em funções monádicas. Primeiro, vamos cuidar do possível fracasso no goLeft e no goRight. Até agora, o fracasso de funções que poderiam falhar sempre se refletia em seu resultado, e desta vez não é diferente. Então, aqui estão goLeft e goRight com uma possibilidade adicional de falha: Cool, agora, se tentarmos dar um passo à esquerda de uma árvore vazia, obtemos nada. Parece bom. Que tal subir. O problema antes aconteceu se tentássemos subir, mas nós não tínhamos mais trilhos, o que significava que já estávamos na raiz da árvore. Esta é a função goUp que lança um erro se não nos mantivermos dentro dos limites da nossa árvore: agora vamos modificá-lo para falhar com graça: se temos migalhas de mapas, tudo está bem e devolvemos um novo foco bem-sucedido, mas se não, então Devolvemos um fracasso. Antes, essas funções usavam zíperes e recuperavam zíperes, o que significava que poderíamos encadear-lhes assim para caminhar: mas agora, em vez de retornar Zipper a. Eles retornam talvez (Zipper a). Então as funções de encadeamento como esta não funcionarão. Tivemos um problema semelhante quando lidamos com nosso caminante de cordas bambas no capítulo sobre mônadas. Ele também caminhou um passo de cada vez e cada um de seus passos poderia resultar em fracasso porque um monte de pássaros podiam pousar de um lado do pólo de equilíbrio e fazê-lo cair. Agora, as piadas sobre nós, porque os que estavam caminhando e atravessavam um labirinto de nossa própria invenção. Felizmente, podemos aprender com o caminante da corda bamba e apenas fazer o que ele fez, o que é trocar a aplicação da função normal pelo uso de gtgt. Que tem um valor com um contexto (no nosso caso, o Talvez (Zipper a), que tem um contexto de possível falha) e o alimenta em uma função, assegurando-se de que o contexto seja ocupado. Assim, assim como nosso caminhante de corda bamba, iriam negociar em todos os nossos -: operadores para gtgt. Tudo bem, podemos encadear nossas funções novamente. Assista: Nós usamos o retorno para colocar um zíper em um gtgt Just e then used para alimentar isso para a nossa função goRight. Primeiro, fizemos uma árvore que tem à sua esquerda uma sub-árvore vazia e à sua direita um nó que possui duas sub-árvores vazias. Quando tentamos ir logo uma vez, o resultado é um sucesso, porque a operação faz sentido. Ir bem duas vezes está bem, também acabamos com o foco em uma sub-árvore vazia. Mas ir três vezes não faz sentido, porque não podemos ir à direita de uma sub-árvore vazia, e é por isso que o resultado é um Nada. Agora nós equipamos nossas árvores com uma rede de segurança que nos atrairá, se nós caíssemos. Uau, eu preguei essa metáfora. Nosso sistema de arquivos também tem muitos casos em que uma operação pode falhar, como tentar se concentrar em um arquivo ou pasta que não existe. Como um exercício, você pode equipar o nosso sistema de arquivos com funções que falham graciosamente ao usar as Monitórias de Assunção Assistida de Oklahoma. O Oklahoma define uma instalação de vida assistida como um centro de vida assistida que presta serviços de apoio a duas ou mais pessoas que precisam de ajuda Com cuidados pessoais e supervisão, transferência, amalgama ou assistência médica. Instalações de assistência assistencial de Oklahoma Âmbito de atendimento Cada provedor vivo assistido pode determinar o escopo de cuidados de suas instalações, que pode incluir unidades de Alzheimer, administração de medicamentos, ajuda com cuidados pessoais, serviços de enfermagem intermitente, ajuda com ambulação ou transferência e ajuda na orientação cognitiva. Um órgão de cuidados paliativos ou de cuidados de saúde em casa pode fornecer serviços adicionais conforme necessário, mas são contratados pelo residente e de acordo com as ordens dadas pelo médico residente. Requisitos de admissão à vida assistida de Oklahoma Em uma instalação de vida assistida em Oklahoma, um residente não pode ser permitido, que precisa de mais cuidados do que a instalação pode razoavelmente fornecer. Se um residente pode ser uma ameaça para si próprio ou para outros, se ele ou ela precisa de restrições químicas ou físicas, ou se a instalação sente que não pode atender às necessidades dos residentes por privacidade ou dignidade, a instalação não pode admitir a pessoa como residente . Requisitos do Plano de Assistência Assistida em Oklahoma Um plano escrito deve estar em vigor para todos os residentes e deve ser revisado trimestralmente por um profissional de saúde licenciado. Se tanto a instalação quanto o residente não concordam com as acomodações no plano de atendimento, a facilidade pode terminar a residência do cliente. Oklahoma Assisted Living Medication Management Requirements A administração de medicamentos é permitida por funcionários não licenciados, embora eles devem receber treinamento em um programa que foi revisado e aprovado pelo Departamento de Saúde de Ohio. Requisitos da Facilidade de Vida Assistida de Oklahoma O design da instalação deve ser efetivo para atender às necessidades físicas e físicas dos moradores, permitindo não mais do que dois residentes por quarto, e os banheiros completos devem estar disponíveis para cada quatro residentes. Oklahoma Assisted Living Staffing Requirements O pessoal de assistência direta deve ser suficiente em número para atender às necessidades dos residentes. Todos os funcionários devem ser submetidos a uma verificação de antecedentes, e a equipe de atendimento direto deve ser treinada em RCP e primeiros socorros. Os CNAs devem estar sob a supervisão direta de uma enfermeira registrada. Um administrador do centro de vida assistida deve possuir uma licença para administradores de enfermagem, um certificado de treinamento para administradores de casas residenciais ou um certificado de treinamento e competência assistido reconhecido nacionalmente, que foi aprovado pelo Departamento de Saúde de Ohio. Política de Medicaid de Assisted Living de Oklahoma Um programa de certificação de renúncia de Medicaid para centros de vida assistida foi iniciado em Oklahoma em 2009. Requisitos da Unidade de Alzheimer de Oklahoma Se uma unidade de vida assistida em Oklahoma tiver uma unidade de Alzheimer, então, algumas divulgações escritas são necessárias. Além disso, o pessoal que trabalha na unidade deve ter treinamento específico para trabalhar com essa população. Pelo menos uma equipe de pessoal especialmente treinada deve estar presente na unidade em todos os momentos. Políticas adicionais aplicam-se a essas unidades. Cobertura de Medicaid de Oklahoma da Vida Assistida e Serviços Relacionados O Estado de Oklahoma paga por serviços em comunidades de comunidades assistidas através da Dispensa do Programa Advantage Medicaids. O Oklahoma ADvantage Program Waiver destina-se a ajudar os idosos frágeis a permanecerem em casa em vez de em uma casa de repouso. Os participantes no programa têm várias opções de serviço de cuidados de longa duração que permitem que o estado gerencie e supervisione os serviços de atendimento que eles recebem. Participants also have a self-direct option. The self-direction option is offered through the Consumer-Directed Personal Assistance Services amp Supports (CD-PASS). Under this plan, participants are able to choose their own personal care providers. Family members are eligible to be hired and paid for their caregiving. The CD-PASS option is not available in all counties at this time. Click on this Oklahoma Department of Human Services link to find out if the program is available in your county. The ADvantage Waiver Services and Benefits Participants can be approved to receive any of the following: - Adult Day Health Care - Disposable Medical Supplies - Home Modifications for Improved Access - Home Delivered Meals - Personal Assistance Services - Specialized Medical Equipment How to apply - you can find out if a waiting list exists by contacting your local Human Services Office or call 1-800-435-4711. What is the best number to call to get started 1-800-435-4711 Additional Oklahoma Medicaid option available to senior citizens that may not have a waiting list: Oklahoma Adult Day Services for the Elderly The Adult Day (Care) Services for the Elderly Program helps residents who need nursing home or assisted living care. The program covers some or all of the cost of adult day care. Services delivered by the adult day care allows an individual to remain living at home or with family members and still receive the level of care they require without being placed in 247 residential care. Individuals are assessed and if approved, a Care Delivery Plan is created. Adult Day Care (Centers) Benefits and Services - Assistance with the activities of daily living personal care - Basic nursing services How to apply - an individual should first select the Adult Day Care Center within the area that you wish to attend and then request assistance. To find an adult day care center use this free service . Learn about the program on the Department of Human Services webpage or call 1-800-498-7995. Department of Health, Protective Health Services Phone (405) 271-6868 Contact: Darlene Simmons (licensure) Phone (405) 271-6868 Mary Fleming, RN (inspection) Oklahoma Contacts Oklahoma Department of Health, Protective Health Services Contact : Darlene Simmons (licensure) Phone: (405) 271-6868 Email: Contact : Mary Fleming, RN (inspection) Email: License information source: Oklahomas Official Web Site Oklahoma Assisted Living Facilities by City

Comments

Popular posts from this blog

Japanese Candlesticks By Steve Nison Pdf

Jurisprudência Stock Options Licenciement

Dcw Forex