2015-11-20 49 views
8

这种C代码可在概念上被描述为创建新阵列相同的输入阵列,但以1作为第一个元素:Haskell中:使用最后一个引用一个变量以有效地创建一个新的变量

int* retire_and_update(int* arr) { 
    arr[0] = 1; 
    return arr; 
} 

这是一个纯函数(wink wink nudge nudge),只要对输入数组及其元素没有进一步的引用。 C型系统不会为我们强制执行,但原则上似乎是可强制执行的。

该GCC生成的代码是简单和有效的:

retire_and_update: 
    movq %rdi, %rax 
    movl $1, (%rdi) 
    ret 

我们功能通过创建在恒定时间一个全新的阵列和不使用额外的存储器实现似乎是不可能。尼斯。 Haskell函数是否可以使用类似的代码有效地实现类似于数组的输入和输出?有没有一种方法可以表达“这是对这个变量的最后一个引用”,这样一个纯函数可以在后台调用变量?

如果函数被内联,那么在这里没有什么有趣的事情需要发生,所以我们假设调用者和函数将被单独编译。

+7

IIUC“独特性类型”,或类似的线性类型,做到这一点。不幸的是,这些不是Haskell类型系统的一个特性。 Haskell中的传统方法是使用[ST' monad](https://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Monad-ST.html)在概念上实现突变纯粹的设置(它暂时进入一个具有可变状态的monad,但类型系统保证计算是确定性的,并且状态不会泄漏)。这与你所谈论的内容完全不同。 – luqui

+3

[Clean](http://clean.cs.ru.nl/Clean)是一种使用唯一类型的函数式语言,也受Haskell的影响。 – chi

回答

6

虽然ST monad而不是正是你所描述的,实际上你可以使用STUArray来实现大部分。所以,一个模拟了你的代码可能是这样的:

import Control.Monad (forM_) 
import Control.Monad.ST (ST) 
import Data.Array.Unboxed (UArray) 
import Data.Array.ST (STUArray, newArray, readArray, writeArray, runSTUArray) 

retire_and_update :: STUArray s Int Int -> ST s (STUArray s Int Int) 
retire_and_update arr = do 
    writeArray arr 0 1 
    return arr 

,如果你有哪些变异就地阵列,像另一个功能:

mutate_inplace :: STUArray s Int Int -> Int -> ST s() 
mutate_inplace arr size = do 
    forM_ [2..size - 1] $ \i -> do 
     a <- readArray arr (i - 2) 
     b <- readArray arr (i - 1) 
     writeArray arr i (a + b) 

你可能绑定两个不纯的功能一起使用runSTUArray他们一个纯函数内:

run :: Int -> UArray Int Int 
run size = runSTUArray $ do 
    arr <- newArray (0, size - 1) 0 
    retire_and_update arr 
    mutate_inplace arr size 
    return arr 

注意run保持纯洁,早期版本返回数组不被泄漏出来的任何地方

\> run 8 
array (0,7) [(0,1),(1,0),(2,1),(3,1),(4,2),(5,3),(6,5),(7,8)] 
+0

已经过了一年了,但是这个答案刚刚跨过我的脑海,我想检查一下我是否了解它,现在我有一个问题。你为什么说'ST monad'不太适合这个问题?你只是指在monad中保持状态的额外输入和概念问题吗?或者是被迫在某处创建副本的实现?谢谢。 – Praxeolitic

+0

@Praxeolitic有*没有*复制; ST monad(与[State Monad]](https://wiki.haskell.org/State_Monad)相反)确实在原地发生了变异。 ST Monad的观点是在类型系统中突变变成_explicit_。但是它不提供['唯一性类型](https://en.wikipedia.org/wiki/Uniqueness_type)提供的保证。 –