我是函数式编程的新手,我决定在Purescript中构建一个应用程序.我遇到了第一个障碍,我不确定如何从概念上思考这个问题.
我不是在寻找代码,而是在功能上思考这个问题.
我有一个数据列表.具体来说,就像
[ {a :: String, b :: String, c :: String} ]
我想通过使用提供的记录(以及上面类型的列表)创建Html
(这是一种purescript-halogen
类型)的列表.
所以,我会有一个功能
buildElements :: forall p i. MyRecordObject -> Array (HTML p i)
现在,我想我需要给这个函数结果类型一个Monad计算上下文(purescript Eff
就像Haskell IO
)
所以类似于:
buildElements :: forall p i. MyRecordObject -> Eff (Array (HTML p i))
我的第一个想法是模糊地创建一个类似的列表
take $ length xs $ repeat ARecordObject
然后将记录映射到该列表,但我不确定如何将其转换为代码.无论如何,这似乎是错误的,因为我的计划涉及改变状态ARecordObject
,这是一个禁忌.
那么我发现了这个功能:
forEach :: forall e a. Array a -> (a -> Eff e Unit) -> Eff Unit
看起来几乎完美!我得到一个数组,我给它一个函数,以某种方式将记录中的属性分配给这个新数组......但不,等等......我正在考虑非功能性.
我真的在这里有点亏.基本上,我想创建类似于元素列表的东西,我在其中为每个项目分配属性.
例如
我提供了一条记录:
[ { id: "id1", name: "name1", class: "class1", content: "content1" } , { id: "id2", name: "name2", class: "class2", content: "content2" } ]
我想要一个foo
返回数组的函数:
[ li [ id_ rec.id, name_ rec.name, class_ rec.class ] [ text rec.content ] , li [ id_ rec.id, name_ rec.name, class_ rec.lass ] [ text rec.content ] ]
其中rec
是recordObject的名称(显然这两个数组不相同,但实际上映射在初始记录上).
(点语法是类似于标准getter/setter表示法的purescript记录语法表示法)
我的第一个想法是模糊地创建一个类似的列表
take $ length xs $ repeat ARecordObject然后将记录映射到该列表,但我不确定如何将其转换为代码.无论如何,这似乎是错误的,因为我的计划涉及改变状态
ARecordObject
,这是一个禁忌.
功能程序员不仅避免变异,因为它是禁忌(实际上,许多功能程序都会谨慎使用受控剂量的可变性) - 我们这样做是因为它产生更安全,更简单的代码.
也就是说:你正在考虑我称之为"alloc-init模式",其中你创建了某种"空"值,然后继续计算它的属性.原谅我的愤怒,但这是一个从根本上破坏的编程模型,从手动内存管理的时代遗留下来; 使用它的代码永远不会安全,依赖它的抽象将永远是漏洞.这个成语不适合任何比C更高级的语言,然而,如果我每次看到这样的代码时都有一英镑......
var foo = new Foo(); foo.Bar = new Bar(); foo.Bar.Baz = new Baz();
......我会成为一个有钱人(娜娜娜).默认应该是在您知道它们的外观后创建对象:
var foo = new Foo(new Bar(new Baz()));
这更简单 - 你只是计算一个值,而不是到达指针所引用的内存以更新其内容 - 更重要的是它更安全,因为类型检查器确保你没有忘记属性它允许你使Foo
不可变的.最干净的命令性代码是功能代码 - 只有在必要的性能(或语言强迫你的手)时,你才应该这样做.
无论如何,咆哮过来.重点在于,通过强制性思考,你使自己的生活变得更加艰难.只需编写一个从单个对象计算单个函数的函数......
toLi :: MyRecord -> HTML toLi x = li [ id_ x.id, name_ x.name, class_ x.class ] [ text x.content ]
...(请注意,我不是以某种方式创建一个"空" li
然后填充其值),然后map
它在您的输入列表上.
toLis :: [MyRecord] -> [HTML] toLis = map toLi
这就是我在JS中的表现,即使我不需要语言.没有副作用,没有突变,不需要Eff
- 只是简单,安全,纯粹的功能代码.