Предположим,
read :: MVector s a -> Int -> a
, что означает read
чисто. Рассмотрим
main :: IO ()
main = do
cell <- replicate 1 'a' -- cell = ['a']
print $ read cell 1 -- we want to print 'a'
write cell 1 'z' -- cell = ['z']
print $ read cell 1 -- we want to print 'z'
Что-то пошло не так: я написал read cell 1
дважды, передав одинаковые cell
и 1
аргументы, поэтому два вызова должны возвращать одно и то же значение. Вот что значит для read
быть чистым. Выше должно быть равно
main :: IO ()
main = do
cell <- replicate 1 'a' -- cell = ['a']
let contents = read cell 1 -- contents = 'a'
print contents -- prints 'a'
write cell 1 'z' -- cell = ['z']; definitely should not affect contents
print contents -- prints 'a'
Но мы не хотим этого: мы хотим, чтобы read
возвращало разные вещи, даже когда мы передаем одни и те же аргументы, принимая во внимание любые write
s, которые могутслучилось между ними. Следовательно, read
должно быть монадическим действием.
Это отличается от length
. Длина вектора никогда не меняется, даже если вектор изменчив;длина фиксированная при создании. Следовательно, length
является чистой функцией;не имеет значения, какие монадические действия вы выполнили между созданием вектора и запросом его длины;это всегда будет одним и тем же.