使用State-Monad的Haskell中的类集合方法 [英] Class set method in Haskell using State-Monad

查看:325
本文介绍了使用State-Monad的Haskell中的类集合方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近看过Haskell的Monad-State。我已经能够创建使用这个Monad的功能,但是我试图将这个行为封装到一个类中,基本上我试图在Haskell中复制这样的东西:

  class A {
public:
int x;
void setX(int newX){
x = newX;
}
void getX(){
return x;
}
}

如果有人能帮忙,我将非常感谢。谢谢!

解决方案

我开始注意到Haskell,至少说,鼓励传统的OO式发展;相反,它具有很好的功能和特征,可以让您在许多其他语言中找不到纯功能操作。短暂的是,试图从其他(传统语言)中引用概念往往是一个非常糟糕的主意。


我试图将行为封装到一个类中


因此,我想到的第一个主要问题是为什么?当然,你必须用这个(传统的OO概念)类来做某事吗?



如果这个问题的一个大致的答案是:我想建模一些数据结构,那么你最好使用像

 数据A = A {xval :: Int} 

> let obj1 = A 5
> xval obj1
5
> let obj2 = obj1 {xval = 10}
> xval obj2
10

其中演示了纯粹的,不可变的数据结构以及getter函数和破坏性更新(利用记录语法)。这样,您可以根据需要,将这些数据结构映射到新的数据结构的功能组合进行任何所需的工作。



现在,如果你绝对需要一些国家的模式(实际上,回答这个问题需要一点经验才能确切地了解本地与全球国家的区别),仅限于那么你会深入使用状态Monad,其中包含以下内容:

  module StateGame where 

import Control.Monad.State

- 使用状态monad
- 传递字典字符串{a,b,c}
- 游戏是从字符串中产生一个数字。
- 默认情况下,游戏关闭,C切换
- 游戏开启和关闭。 A'a'给出+1和a给出-1。
- Eg
- 'ab'= 0
- 'ca'= 1
- 'cabca'= 0
- 状态=游戏是开或关当前得分
- =(Bool,Int)

类型GameValue = Int
类型GameState =(Bool,Int)

playGame :: String - > State GameState GameValue
playGame [] = do
(_,score)< - get
return score

playGame(x:xs)= do
(on,score)< - get
case x of
'a'| on - > put(on,score + 1)
'b'| on - > put(on,score - 1)
'c' - > put(not on,score)
_ - > put(on,score)
playGame xs

startState =(False,0)

main = print $ evalState(playGameabcaaacbbcabbab)startState

(无耻地从本教程)。请注意,除了'put'和'get'单体功能之外,还可以使用状态monad的上下文中类似的纯不可变数据结构,这有助于访问状态中包含的状态Monad。



最终,我建议你问问自己:你真的想用这个(OO)类的模式完成什么? Haskell不是您的典型的OO语言,并且尝试将概念映射到1到1将只会使您在短期(甚至长期)期间失败。这应该是一个标准的口头禅,但我强烈建议您从书中 Real World Haskell 学习,其中作者能够深入了解更为详细的动机来挑选任何一种工具或抽象。如果你坚持,你可以在Haskell中建模传统的OO结构,但是我不会建议你去做这个,除非你有一个真正的的理由。


I've recently had a look at Haskell's Monad - State. I've been able to create functions that operate with this Monad, but I'm trying to encapsulate the behavior into a class, basically I'm trying to replicate in Haskell something like this:

class A {
  public:
  int x;
  void setX(int newX) {
      x = newX;
  }
  void getX() {
      return x;
  }
}

I would be very grateful if anyone can help with this. Thanks!

解决方案

I would start off by noting that Haskell, to say the least, does not encourage traditional OO-style development; instead, it has features and characteristics that lend themselves well to the sort of 'pure functional' manipulation that you won't really find in many other languages; the short on this is that trying to 'bring over' concepts from other (traditional languages) can often be a very bad idea.

but I'm trying to encapsulate the behavior into a class

Hence, my first major question that comes to mind is why? Surely you must want to do something with this (traditional OO concept of a) class?

If an approximate answer to this question is: "I'd like to model some sort of data construct", then you'd be better off working with something like

data A = A { xval :: Int }

> let obj1 = A 5
> xval obj1
5
> let obj2 = obj1 { xval = 10 }
> xval obj2
10

Which demonstrates pure, immutable data structures, along with 'getter' functions and destructive updates (utilizing record syntax). This way, you'd do whatever work you need to do as some combination of functions mapping these 'data constructs' to new data constructs, as appropriate.

Now, if you absolutely needed some sort of model of State (and indeed, answering this question requires a bit of experience in knowing exactly what local versus global state is), only then would you delve into using the State Monad, with something like:

module StateGame where

import Control.Monad.State

-- Example use of State monad
-- Passes a string of dictionary {a,b,c}
-- Game is to produce a number from the string.
-- By default the game is off, a C toggles the
-- game on and off. A 'a' gives +1 and a b gives -1.
-- E.g 
-- 'ab'    = 0
-- 'ca'    = 1
-- 'cabca' = 0
-- State = game is on or off & current score
--       = (Bool, Int)

type GameValue = Int
type GameState = (Bool, Int)

playGame :: String -> State GameState GameValue
playGame []     = do
    (_, score) <- get
    return score

playGame (x:xs) = do
    (on, score) <- get
    case x of
         'a' | on -> put (on, score + 1)
         'b' | on -> put (on, score - 1)
         'c'      -> put (not on, score)
         _        -> put (on, score)
    playGame xs

startState = (False, 0)

main = print $ evalState (playGame "abcaaacbbcabbab") startState

(shamelessly lifted from this tutorial). Note the use of the analogous 'pure immutable data structures' within the context of a state monad, in addition to 'put' and 'get' monadic functions, which facilitate access to the state contained within the State Monad.

Ultimately, I'd suggest you ask yourself: what is it that you really want to accomplish with this model of an (OO) class? Haskell is not your typical OO-language, and trying to map concepts over 1-to-1 will only frustrate you in the short (and possibly long) term. This should be a standard mantra, but I'd highly recommend learning from the book Real World Haskell, where the authors are able to delve into far more detailed 'motivation' for picking any one tool or abstraction over another. If you were adamant, you could model traditional OO constructs in Haskell, but I wouldn't suggest going about doing this - unless you have a really good reason for doing so.

这篇关于使用State-Monad的Haskell中的类集合方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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