我正在编写一个程序,其中包含几个具有相同参数的函数.为简单起见,这是一个有点人为的例子:
buildPhotoFileName time word stamp = show word ++ "-" ++ show time ++ show stamp
buildAudioFileName time word = show word ++ "-" ++ show time ++ ".mp3"
buildDirectoryName time word = show word ++ "_" ++ show time
Run Code Online (Sandbox Code Playgroud)
假设我在IO上循环一个资源以在运行时获取time和word参数.在这个循环中,我需要加入上述函数的结果以便进一步处理,所以我这样做:
let photo = buildPhotoFileName time word stamp
audio = buildAudioFileName time word
dir = buildDirectoryName time word
in ....
Run Code Online (Sandbox Code Playgroud)
这似乎违反了"不要重复自己"的原则.如果我在路上发现我想改成word函数word,我可能会在let表达式的开头创建一个新的绑定,如下所示:
let wrd = processWord word
photo = buildPhotoFileName time wrd stamp
audio = buildAudioFileName time wrd
dir = buildDirectoryName time wrd
in ....
Run Code Online (Sandbox Code Playgroud)
并会在每次我写的时间来改变word到wrd,从而导致错误,如果我记得更改某些函数调用,而不是其他.
在OOP中,我会通过将上述功能中的一类,其构造函数会采取解决这个问题time,并word作为参数.实例化的对象基本上是cur time和的三个函数word.如果我想确保函数接收processWord word而不是word作为"参数",我可以调用processWord构造函数.
有什么更好的方法可以更适合函数式编程和Haskell?
Nik*_*kov 11
既然你说你已经准备好为此创建一个OO-wrapper-class,我假设你愿意改变你的功能.以下是一个函数,生成您想要的所有三个结果的元组:
buildFileNames time word stamp =
( show word ++ "-" ++ show time ++ show stamp,
show word ++ "-" ++ show time ++ ".mp3",
show word ++ "_" ++ show time )
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它:
let wrd = processWord word
(photo, audio, dir) = buildFileNames time wrd stamp
in ....
Run Code Online (Sandbox Code Playgroud)
如果你不需要任何结果,你可以像这样跳过它们:
let wrd = processWord word
(_, audio, _) = buildFileNames time wrd stamp
in ....
Run Code Online (Sandbox Code Playgroud)
值得注意的是,您不必担心Haskell会浪费资源来计算您不使用的计算值,因为它很懒惰.
你在OOP土地上描述的解决方案对我来说听起来像是一个很好的解决方案.以机智:
data UID = UID
{ _time :: Integer
, _word :: String
}
Run Code Online (Sandbox Code Playgroud)
在此记录中包括或不包括"标记"是一项设计决定,我们可能没有足够的信息在这里回答.可以将此数据类型放在其自己的模块中,并定义"智能构造函数"和"智能访问器":
uid = UID
time = _time
word = _word
Run Code Online (Sandbox Code Playgroud)
然后隐藏在模块边界,如真正的构造函数和存取出口UID型,uid智能构造,以及time与word智能存取,而不是UID构造函数或_time和_word存取.
module UID (UID, uid, time, word) where
Run Code Online (Sandbox Code Playgroud)
如果我们后来发现智能构造函数应该进行一些处理,我们可以改变以下定义uid:
uid t w = UID t (processWord w)
Run Code Online (Sandbox Code Playgroud)
建立在Nikita Vokov的答案之上,您可以使用记录通配符来获得一些简洁的语法,几乎不重复:
{-# LANGUAGE RecordWildCards #-}
data FileNames = FileNames { photo :: String, audio :: String, dir :: String }
buildFileNames :: Word -> Time -> Stamp -> FileNames
buildFileNames time word stamp = FileNames
(show word ++ "-" ++ show time ++ show stamp)
(show word ++ "-" ++ show time ++ ".mp3")
(show word ++ "_" ++ show time )
let FileNames {...} = buildFileNames time wrd stamp
in ... photo ... audio ... dir...
Run Code Online (Sandbox Code Playgroud)