2015-04-20 1 views
3

Когда я разрабатываю некоторые анализы данных в конвейерах в haskell, часто бывает полезно предварительно загрузить состояние переменной в GHCi после загрузки.Автоматическая перезагрузка состояния переменной в GHCi при повторной загрузке файла

Что я сейчас делаю, это копирование и вставка частей сценария по очереди в emacs только для проверки и проверки вывода некоторой промежуточной обработки. Я не могу даже набросать код для копирования, потому что разрывы строк не передаются (по крайней мере, в режиме Emacs Interactive-Haskell)

Есть ли способ сделать это?

EDIT: просто загрузка/перезагрузка файла .hs не делает трюка, потому что у afaik нет способа иметь «< -» привязки на верхнем уровне.

+0

Почему бы не превратить его в функцию/выражение и загрузить его? Или упаковать его в обычный модуль и просто загрузить его в ghci? – Carsten

+0

, потому что я хочу использовать ghci для интерактивного анализа/тестирования с переменными внутри функции. – daj

+0

Можете ли вы привести пример? Я не думаю, что правильно понимаю: обычно вы можете упаковать все, что вы используете, в файл .hs и просто загрузите его в ghci – Carsten

ответ

0

Есть два основных способа сделать это:

  • Используйте :l [filename] GHCi команду, чтобы перезагрузить файл без выхода из GHCI.
  • Запишите переменные в файле ~/.ghci, который будет загружен при открытии GHCi.

Если вы не знаете, что положить в ~/.ghci, вот что я имею в шахте:

:set prompt "\955 " 
:set prompt2 "| " 

:def hoogle \x -> return $ ":!hoogle --info \"" ++ x ++ "\"" 

let f `on` x = \a b -> (f a) `x` (f b) 
let break (f,g) = \a -> (f a, f g) 
+1

перезагрузка файла не делает трюк. Насколько я могу судить, я не могу делать привязки на верхнем уровне с «<-». Файлы .ghci работают. одна интересная вещь, которую я заметил с emacs: у меня может быть любой файл с расширением .ghci (например, currWork.ghci), загружать его в интерпретатор через C-c и C-l, и он работает как скрипт, который скопирован. Таким образом, у меня могут быть небольшие интерактивные загрузчики состояний для каждой задачи (вместо того, чтобы сбрасывать все в один глобально используемый файл .ghci). – daj

+1

'<-' работает в интерактивном режиме. Например: вы можете набрать 'str <- getLine' в ghci и запустить' getLine' и связать все, что вы набираете, с 'str' –

3

Я предлагаю вам взглянуть на foreign-store. Он позволяет ссылаться на переменные по номерам, которые сохраняются при перезагрузке. Вот пример:

λ: :set -XScopedTypeVariables 
λ: import Foreign.Store 
λ: st <- newStore "example" 
Loading package foreign-store-0.2 ... linking ... done. 
λ: readStore st 
"example" 
λ: st 
Store 0 
λ: :r 
Ok, modules loaded: none. 
λ: st 
<interactive>:8:1: 
    Not in scope: ‘st’ 
    Perhaps you meant ‘fst’ (imported from Prelude) 
λ: Just (st :: Store String) <- lookupStore 0 
λ: readStore st 
"example" 

Кроме того, вы также можете поместить все ваши определения в одном файле ГВ и только перезагрузить это. Вы можете использовать unsafePerformIO, чтобы обойти ограничение, которое вы не можете использовать <- на верхнем уровне. Я думаю, что это нормально в этом случае, так как вы используете его только для интерактивных:

module Example where 

import System.IO.Unsafe 

example :: String 
example = "example" 

file :: String 
file = unsafePerformIO $ readFile "/tmp/example.hs" 
+0

Да, я просто использую' unsafePerformIO' для этой цели. Недостатком является то, что переменная должна быть пересчитана при каждой перезагрузке; если вычислить его довольно дорого, то подход к иностранному магазину может быть лучше. –

+0

@ReidBarton Да, вы даже можете объединить unsafePerformIO с иностранным магазином: создать чужой магазин, выполнить дорогостоящую операцию и использовать unsafePerformIO для создания lookupStore в файле. – bennofs