首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用State重构代码,以便通过添加更多的函数来增加模块化?

如何使用State重构代码,以便通过添加更多的函数来增加模块化?
EN

Stack Overflow用户
提问于 2016-10-31 02:36:17
回答 1查看 116关注 0票数 0

我在试着掌握单元组的诀窍。我想这是个很好的练习。

使用来自CLaSH的UART

代码语言:javascript
复制
-- UART RX Logic
data RxReg
  = RxReg
  { _rx_reg        :: BitVector 8
  , _rx_data       :: BitVector 8
  , _rx_sample_cnt :: Unsigned 4
  , _rx_cnt        :: Unsigned 4
  , _rx_frame_err  :: Bool
  , _rx_over_run   :: Bool
  , _rx_empty      :: Bool
  , _rx_d1         :: Bit
  , _rx_d2         :: Bit
  , _rx_busy       :: Bool
  }

makeLenses ''RxReg

uartRX r@(RxReg {..}) rx_in uld_rx_data rx_enable = flip execState r $ do
  -- Synchronise the async signal
  rx_d1 .= rx_in
  rx_d2 .= _rx_d1
  -- Uload the rx data
  when uld_rx_data $ do
    rx_data  .= _rx_reg
    rx_empty .= True
  -- Receive data only when rx is enabled
  if rx_enable then do
    -- Check if just received start of frame
    when (not _rx_busy && _rx_d2 == 0) $ do
      rx_busy       .= True
      rx_sample_cnt .= 1
      rx_cnt        .= 0
    -- Star of frame detected, Proceed with rest of data
    when _rx_busy $ do
      rx_sample_cnt += 1
      -- Logic to sample at middle of data
      when (_rx_sample_cnt == 7) $ do
        if _rx_d1 == 1 && _rx_cnt == 0 then
          rx_busy .= False
        else do
          rx_cnt += 1
          -- start storing the rx data
          when (_rx_cnt > 0 && _rx_cnt < 9) $ do
            rx_reg %= replaceBit (_rx_cnt - 1) _rx_d2
          when (_rx_cnt == 9) $ do
            rx_busy .= False
            -- Check if End of frame received correctly
            if _rx_d2 == 0 then
              rx_frame_err .= True
            else do
              rx_empty     .= False
              rx_frame_err .= False
              -- Check if last rx data was not unloaded
              rx_over_run  .= not _rx_empty
  else do
    rx_busy .= False

我将如何将when逻辑移动到它们自己的函数中?我玩这个已经有一点了,但是镜头似乎引起了一些问题。

代码语言:javascript
复制
Could not deduce Control.Monad.State.Class.MonadState from .=

我认为有一个函数这里

我错过了。

我想做这样的事

代码语言:javascript
复制
newFun = when (not _rx_busy && _rx_d2 == 0) $ do
         rx_busy       .= True
         rx_sample_cnt .= 1
         rx_cnt        .= 0

我想我需要一个像execState这样的函数。

所以我的问题是,

  • 我该用什么?
  • 这个函数是做什么的,使它能够与其他函数组合?
  • 如果monads只是在作曲,我为什么不能将when放在一个没有execState类型函数的函数中呢?
  • 还有什么其他方法可以提高代码的模块化呢?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-31 02:42:41

newFun的定义中

代码语言:javascript
复制
newFun = when (not _rx_busy && _rx_d2 == 0) $ do
         rx_busy       .= True
         rx_sample_cnt .= 1
         rx_cnt        .= 0

您正在尝试引用_rx_busy_rx_d2,它们是RxReg类型的记录字段。在uartRX中,第一个参数是RxReg,RecordWildCards语言扩展通过将参数与模式RxReg{..}匹配来绑定所有字段名。因此,您需要将r本身,或者至少是_rx_busy_rx_d2,从uartRX传递到newFun;也就是说,要么有

代码语言:javascript
复制
newFun busy d2 = when (not busy && d2 == 0) $ do
    ...

代码语言:javascript
复制
newFun RxReg{..} = when (not _rx_busy && _rx_d2 == 0) $ do
    ...
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40335878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档