我想在名为Director
的数据类型billy
变量的“电影”列表中添加一个元素。
type Name = String
type Movie = String
data Director = Director {name:: Name, movies::[Movie]}
deriving (Show)
let billy = Director "Billy J." ["Good movie 1"]
--addMovieToDirector :: Movie -> Director -> Director
addMovieToDirector m (Director n ms) = Director n (m:ms)
问题是以前的功能没有更新比利的电影列表,它会创建一个带有所需列表的新Director
(更改不存储在比利上)。如何在不创建另一个Director
的情况下在比利的列表上操作?我理解,Haskell使用常量,但是每次修改列表时我应该创建一个不同的'billy'“变量”吗?
谢谢!
答案 0 :(得分:7)
您想要做的是“就地修改”或“使用可变数据”。
Haskell有很多方法可以做到这一点。由于任何事物的就地修改几乎总是被视为“副作用”,因此这些事情只能在IO monad中完成,或者使用像unsafePerformIO
这样的诡计。
这些是一些高级主题,在初学者层面上,将Haskell值视为完全不可变是有益的。
所以是的,你无法修改变量。实际上根本没有“变量”。
将billy
视为值的名称,而不是变量。
Haskell中的所有函数都可以接受参数,并计算一些没有任何副作用的结果 。
对于来自命令式语言的人来说,这可能是最大的心理障碍:“如果我无法修改数据,我该如何处理数据?”
答案是:您应该像巨型装配线一样构建您的程序:原材料(原始数据,初始参数等)在开头(您调用的第一个函数)和每个工作站(函数)上线)做一些有用的东西(返回一个值),消耗前一个工作站的结果。最后,有价值的东西可能会脱离生产线。
我所描述的是简单的功能组合:如果您需要在c
之后,b
之后,在值a
上执行x
任务,那么您可以编写它为(c . b . a) x
,或c (b (a x))
或更确切地说c $ b $ a x
。
通过这种方式,您可以编写程序而无需明确地更改任何内容,并且只描述如何使用旧内容创建新内容。
这听起来非常低效,事实上,功能编程有一些性能影响(更不用说懒惰)了。然而,编译器足够聪明,能够弄清楚用Haskell编写的程序,并以某种方式对其进行优化。
我希望很快就会有意义。 :)
哦,欢迎来到Haskell。 ;)
答案 1 :(得分:0)
如果您希望程序中存在可变状态,则可以使用State monad。这是一个例子:
module Main where
import Control.Monad.State
type GameValue = Int
type GameState = (Bool, Int)
type Name = String
type Movie = String
data Director = Director {name:: Name, movies::[Movie]}
deriving (Show)
addMovieToDirector :: Movie -> Director -> Director
addMovieToDirector m (Director n ms) = Director n (m:ms)
handleDirector :: Name -> State Director Director
handleDirector m = do
director <- get
put (addMovieToDirector m director)
returnDirector
returnDirector = do
director <- get
return director
startState = Director "Billy J." ["Good movie 1"]
main = print $ evalState (handleDirector "Good movie 2") startState
打印结果将是
导演{name =&#34; Billy J。&#34;,movies = [&#34; Good movie 2&#34;,&#34; Good movie 1&#34;]}
此类handleDirector
类型Name -> State Director Director
函数在Director
类型中具有可变状态,而#34;结果&#34;类型的值,再次,Director
。 get
表示获取状态,put
用于更改状态,evalstate
用于&#34;计算&#34;结果,由构造的State
monad包围。