如何模拟haskell状态? [英] how to simulate haskell state?

查看:121
本文介绍了如何模拟haskell状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一些haskell代码来切换树莓派上的一个引脚,这取决于我从树莓派另一个引脚获得的中断。我只是不知道如何在不知道以前的切换状态的情况下切换引脚的状态。程序本身非常简单。

  import Control.Concurrent 
import Data.IORef
import HasberryPi


main = do wiringPiSetup
pinMode 0输出
pinMode 7输入
pullUpDnControl 7 pull_down
wiringPiISR 7 edge_both onoff
threadDelay( 15 *(10 ^ 6))

onoff s =做一个< - readIORef s - 这是错误的
digitalWrite 0(如果b然后pinhigh else pinlow) - 这是错误的

因此,基本上这里发生的事情是引脚7被注册为中断。当引脚7从高电平变为低电平或从低电平变为高电平时,触发中断。每当中断被触发时,它会调用切换引脚0状态的 onoff 函数。



main 函数是正确的。它的 onoff 函数是问题所在。 onoff 函数所需的行为是当引脚为低电平时使引脚0变为高电平,当引脚变为高电平时将引脚变为低电平。但要做到这一点,我需要将前一次调用中以前的状态存储到 onoff 中。

我尝试了状态monad。但问题在于状态monad基于初始状态值传递状态。但在随后调用 onoff 时,似乎不可能更改初始状态值。我想到了IORef,似乎没有什么不同。它看起来像是在做什么状态......但只在IO内部。

我可以清楚地看到,我非常想念在全局变量中存储状态的能力。我很高兴我无法做到这一点,因为我知道还有其他一些实现相同目标的惯用方式。



任何对正确方向的帮助都非常感谢。



干杯和问候。

解决方案

c monad实际上是一种抽象概念,参数给你的函数 - 它仍然是纯粹的,它只是给你很多的语法帮助。另一方面, IORef 是实际可变值的实际更新,这就是为什么它必须存在于 IO monad。这通常被认为是不可取的,除非出于性能原因需要,因为你失去了所有关于懒惰和执行顺序以及并发性的纯代码的承诺。使用<$ c通过使用StateT monad变换器可以实现$ c> State 和 IO ,这可能被认为是围绕IO封装State monad单子。 Haskell wiki上有一些例子: http://www.haskell.org/haskellwiki/Simple_StateT_use它展示了如何在使用I / O时保持状态,以及如何使用 lift 来获得IO monad函数在> StateT


I wrote some haskell code to toggle a pin on the raspberry pi depending on an interrupt I get from another pin on the raspberry pi. I simply do not know how to toggle the state of the pin without knowing the previous toggle state. The program itself is very simple.

 import Control.Concurrent
 import Data.IORef
 import HasberryPi


 main = do wiringPiSetup
           pinMode 0 output
           pinMode 7 input 
           pullUpDnControl 7 pull_down
           wiringPiISR 7 edge_both onoff
           threadDelay (15*(10^6))

 onoff s = do a <- readIORef s                               -- This is wrong
              digitalWrite 0 (if b then pinhigh else pinlow) -- This is wrong

So basically what happens here is pin 7 is registered as an interrupt. The interrupt is triggered whenever pin 7 goes from high to low or low to high. And whenever the interrupt is triggered it calls the onoff function that toggles the state of pin 0.

The main function is correct. Its the onoff function that is the problem. The wanted behavior of the onoff function is to make pin 0 high when the pin it is low and toggle the pin low when it is high. But to do that I need to store the previous state of the pin in the previous call to onoff.

I tried the state monad. But the problem is that the state monad passes state around based on an initial state value. But in subsequent calls to onoff it seems impossible to change the initial state value. I thought about IORef and it seems no different. It just seems like it's doing what state is doing.. but only inside the IO.

I can clearly see that I am sorely missing the ability of storing state in a Global variable. And I'm happy that I'm not able to do it because I know there is some other idiomatic way of achieving the same goal.

Any help in the right direction is very much appreciated.

Cheers and Regards.

解决方案

The State monad is really an abstraction over the idea of passing state around in an extra parameter to your functions - it's still pure, it just gives you a lot of syntactic help. IORef, on the other hand, is an actual update of an actual mutable value, which is why it has to live inside the IO monad. This is generally considered undesirable unless required for performance reasons, as you lose all the promises you get with pure code about laziness and order of execution and concurrency.

Using State and IO together is achieved by use of the StateT monad transformer, which might be thought of as wrapping the State monad around the IO monad. There are some examples on the Haskell wiki: http://www.haskell.org/haskellwiki/Simple_StateT_use which shows how you maintain state while using I/O, and how to use lift to get IO monad functions to run inside StateT.

这篇关于如何模拟haskell状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆