回答
im trying to re-assign an existing variable
你不能在Haskell中做到这一点。你可以通过使用IORef
来完成某些事情,但这很少是问题的正确解决方案 - 当然不是初学者可能遇到的情况。
相反,您应该重新设计您的程序逻辑,以便它不需要可变变量的功能。
在这一点上,我怀疑有任何程序逻辑来重新设计。 OP只想知道如何处理Haskell中的其他语言。 –
Haskell是一个伟大的imperative语言,编写可以重新分配状态的程序是一个非常有趣的高级话题!这绝对不是你现在想要的方法,但有一天会回来
它需要一点努力去定义一个模拟全局可变变量的环境。然而,一旦你掌握了它,类型的精确性就变得非常方便了。
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.State
大家都知道,大象是整数。
type Elephant = Integer
你想要一个程序,其全局可变状态有一头大象。首先让我们来定义一下大象的含义。 Lens
很好地捕捉了这个概念。现在
class HasElephant a
where
elephant :: Lens' a Elephant
,我们可以定义function
,它分配一个新的价值elephant
。
function :: (MonadState s m, HasElephant s) => Elephant -> m()
function x =
elephant .= x
约束MonadState s m
和HasElephant s
都在说我们的程序必须能够持有某种类型s
的可变状态,类型s
必须有大象。
我们还定义一个打印大象的程序。
printElephant :: (MonadState s m, HasElephant s, MonadIO m) => m()
printElephant =
use elephant >>= (liftIO . print)
这个程序执行I/O(印刷),所以我们有一个附加的约束MonadIO m
,说我们的节目类型m
必须能够做I/O。
非洲森林大象(Loxodonta cyclotis)是一种在刚果盆地发现的森林栖息物种。
data Congo = Congo
{ _congoElephant :: Elephant
}
makeLenses ''Congo
我们必须定义Congo
有一头大象的方式。
instance HasElephant Congo
where
elephant = congoElephant
现在我们可以编写一个示例程序。我们的程序将打印elephant
的值,然后更改elephant
的值,然后再次打印。
main' :: StateT Congo IO()
main' =
do
printElephant
function 2
printElephant
然后我们可以运行这个程序。
main :: IO()
main = Congo 0 & runStateT main' & void
输出是:
0
2
虽然这些都是很好的事情要知道和使用一般,我觉得这可能不是最合适的时候谈论'StateT',monad变压器,类型和镜头......如果有人不知道这方面的哈斯克尔(没有像C这样的语言的方式赋值)并且以前没有遇到过这种差异,我怀疑他们还没有这方面的背景,甚至可能会吓跑他们(我*可能*是错的当然,但我有一个非常强烈的怀疑......)。 –
@DavidYoung我不指望我的答案会提供任何即时效用的提问者。其他人已经这样做了。这个答案在这里,因为我一直相信,偶尔瞥见一些你还不能理解的东西是有价值的,从你脚下的路径向上看,并注视着山上的云彩形状。 –
这是一个公平点。 –
Haskell是在函数式编程世界和函数式编程的领导者通常被称为“编程不分配。”这几乎是功能编程的整个点不使用分配。一旦你使用它,你就不再以“功能”的方式来做它了。当然有时候,FP会尽量减少这些时间。
所以,要回答你的问题,“为什么不工作?”首先,语法不正确。 =
并不意味着在Haskell中赋值。它将一个名称绑定到一个表达式。你不能这样做两次(在相同的范围内)。换句话说,“变量”是不可变的(就像在数学中一样)。其次,突变是一种副作用行为,Haskell将这些行为视为必须在IO
世界中完成的不纯行为。
我可以告诉你如何实际上变异在Haskell中的引用,但我不认为这就是你需要在这一点上。
到可变x
绑定到值v
最原始的方法是编写的函数采取x
作为参数,并传递给v
该功能。
这有时可以用来“模拟”可变变量的效果。
例如,势在必行代码
// sum 0..100
i = s = 0;
while (i <= 100) {
s = s+i;
i++;
}
return s;
成为
final_s = f 0 0 -- the initial values
where
f i s | i <=100 = f (i+1) (s+i) // increment i, augment s
| otherwise = s // return s at the end
上面的代码是不漂亮FP码,但至少它是足够接近的命令性代码,使其能够当场连接。
最后题外话:
当一个第一通知这一点,它通常是引诱到落入Blub paradox。人们可以很容易想到:“什么!Haskell需要所有的东西来模拟一个简单的任务?如果在语言Blub分配是微不足道的,并且模拟Haskell需要这么多努力,那么显然Blub比Haskell好得多!”。这将是一个完美的Blub悖论案例:当一个Blub程序员转向另一种语言时,他们立即察觉到Blub不能直接翻译的内容,并且没有注意到新语言的所有其他功能并不存在泡壳。 他们的思想现在在“Blub”中思考,它需要付出很大的努力才能适应新的模型。
几乎与此相反,学习都 FP和命令式编程是有用的,因为当仅用于其中的一种时,学习其他范式并非微不足道。如果他们之间的差距很小,那么为了解决同样的问题而学习两种接近的方法是不值得的。
一般来说这不起作用,因为您通常会进行不可变的声明,而不是指定一系列操作。你可以这样做:
elephant = 3
main = print elephant
但你也可以这样做:
main = print elephant
elephant = 3
由于代码不指定执行顺序,也没有办法解释多项任务作为不是错误以外的任何。
如果你想指定的一系列操作,使用做符号:
main = do
let elephant = 0
print elephant
let elephant = 1
print elephant
let elephant = 2
print elephant
在的代码做块顺序执行,这样可以有效地重新分配变量的方式,您可以在大多数编程语言中。
请注意,这段代码实际上只是为大象创建了一个新的绑定。旧的价值依然存在:
main = do
let elephant = 1
print elephant
let printElephant = print elephant
let elephant = 2
print elephant
printElephant
因为printElephant功能我定义依然采用大象的旧值,这样打印:
1
2
1
你确实可以做到这一点,但是强调'let elephant = 1'和'let elephant = 2'确实不**重新分配变量'elephant'很重要。相反,他们只是引入了一个_new_变量,该变量恰好也被称为'大象'。然后,“印象大象”选择最近的一次出现(更确切地说,是_narrowest共享范围内的那个),但在这个范围之外,老大象始终保持相同的值。我建议这不应该在实际的Haskell代码中完成(实际上'ghc-Wall'会警告它)。 – leftaroundabout
@leftaroundabout你说得对,我加了一点来说明不同之处。 此外,我知道这不是建议,但问题违背了语言所代表的一切。用一些可以推荐的东西很难回答这个问题。 –
- 1. MATLAB函数重新分配未定义数量的变量值
- 2. 在JQuery中为变量分配函数
- 3. 如何在Lua中正确地重新分配变量?
- 4. 重新分配变量值
- 5. 在将结构传递给Matlab中的函数时重新分配变量
- 6. Haskell中的多变量函数
- 7. 如何将对象重新分配给python中的变量?
- 8. 重新分配函数变量上的JavaScript
- 9. 如何在函数中分配一个变量值? unix korn shell
- 10. Javascript:无法在递归函数调用中重新分配变量
- 11. python,在每个函数调用中停止变量重新分配?
- 12. 如何从一个定义函数内重新分配一个变量的值?
- 13. 如何在Haskell中重新实现“all”函数?
- 14. 将整数分配给Haskell中的变量
- 15. 如何将连锁函数分配给jQuery中的变量
- 16. 如何重新分配一个新的有价值的变量
- 17. 如何将JavaScript函数中的变量的值分配给Mason变量?
- 18. 在r中的ifelse函数中分配变量
- 19. Python:返回函数变量并分配给新变量
- 20. 在包含的Dwoo模板中重新分配父变量
- 21. 如何在树枝中分配变量?
- 22. 如何在VBA中分配变量?
- 23. 在函数参数中分配一个javascript变量的值?
- 24. JavaScript中的双重变量分配
- 25. Haskell中的变量
- 26. 如何通过分配在FreeMarker的函数变量值
- 27. 强迫变量重新分配(Prolog)
- 28. 重新分配变量不起作用
- 29. 重新分配POST输出变量
- 30. 重新分配变量列表
你要定义一个变量还是要重新 - 分配一个现有的变量?我在问,因为你的例子看起来像你正试图改变全局'elephant'变量的值。 – sepp2k
即时尝试重新分配一个现有的变量。 – Fl4mer
在这两种情况下,我认为你正在击中S.O.太快了,需要学习更多的语法和语言原语。我建议你通过阅读来学习更多的Haskell。例如,[wikibooks](https://en.wikibooks.org/wiki/Haskell)和“函数式编程工艺”是开始的好地方。 –