(仿真)宏在Haskell?
-
18-09-2019 - |
题
在Reddit上的人带来了这个代码了我的注意:
main = do
let ns = [print 1, print 2, print 3]
sequence_ ns
sequence_ $ reverse ns
sequence_ $ tail ns ++ [head ns]
head ns
这是怎么回事是我们业务的一个数组,我们可以做的东西有,像反向或得到它的尾部或头部。
真棒。
我想要做的就是到各个元素,并改变它们为好。举例来说,我希望能够做这样的事:
ns !! 0
和得到类似[打印,1],然后改变最后一个元素,比方说,3.14以便函数将打印3.14。
时,它在所有可能在Haskell或者我应该只是回到LISP?
AN重要编辑:我排序失蹄。我明白,我需要建立一个新的列表。是否有可能得到一个功能,这是一个列表的一部分的论点?我要的是从他们的标识符/参数组合功能,还能够分解功能为标识/参数它被评估之前的能力。
解决方案
有比Lisp更复杂一些,但哈斯克尔元编程,您可以使用模板哈斯克尔
如,[|print 1|]
将被转换为
return $ AppE (VarE $ mkName "print") (LitE $ IntegerL 1)
,其具有类型Q Exp
(表达式的报价)。
如果您想拼接你自己的数据到一个报价,[|print $(foo 3.14)|]
将在编译时执行foo 3.14
。
其他提示
一旦你应用价值的功能,有没有办法把它找回来。尝试包裹的功能和它的数据类型的参数,你可以评估或根据您的需要分解。
data App a b = App (a -> b) a
runApp (App a b) = a b
ns = [App print 1, App print 2, App print 3]
main = do
sequence_ $ map runApp ns
let ns2 = [App fun (arg^2) | App fun arg <- ns]
sequence_ $ map runApp ns2
输出
1
2
3
1
4
9
你想发生变异的名单?你应该回去口齿不清; - )
的值是在Haskell不可变的。哈斯克尔,方法是创建一个新的列表,它等同于旧列表除了最后一个元素。
(有涉及单子,你可以模拟可变值和指针一些技巧,但是这可能不是你想要的这里。)
编辑:不能完全确定我理解编辑的问题,但你可以单独处理功能和参数的数据,然后“应用”后,如;
do
let ns = [(print, 1), (print, 2), (print, 3)]
sequence_ $ map (\(f,a)->f a) ns
就像已经说过Haskell的办法是只创建一个新的列表,但你可以有IO单子里面可变阵列,IOArray如果你真的想
import Data.Array.IO
seqArr_ arr = getElems arr>>=sequence_
main= do
arr <- newListArray (0,2) [print 1,print 2,print 3] :: IO (IOArray Int (IO ()))
seqArr_ arr -- prints 1 2 3
writeArray arr 2 (print 3.14) -- change the last element
seqArr_ arr -- prints 1 2 3.14
不隶属于 StackOverflow