如何在不引起Haskell重新编译的情况下更改数据类型?
在观看了一段视频之后,我受到了启发,写了一个与他在演讲中演示的开发环境有点相似的快速破解 基本上,我们的想法是,让应用程序在一个窗口中运行,只要在源文件中保存更改,程序就会更改 这对于小的更改非常有效,除了我不能在不关闭应用程序并重新编译的情况下更改代码中的状态类型 如何解决表达式问题并使状态的数据类型能够更改 而不会导致重新编译 附言。 这是密码。 我本来不想发帖,因为它真的很乱,而且很快就被砍掉了,但是人们想要它,这样他们就可以得到它 首先是显示器和空闲模块(这是一个快速破解,所以我不知道如何将它们作为真正的模块) Idle.hs如何在不引起Haskell重新编译的情况下更改数据类型?,haskell,Haskell,在观看了一段视频之后,我受到了启发,写了一个与他在演讲中演示的开发环境有点相似的快速破解 基本上,我们的想法是,让应用程序在一个窗口中运行,只要在源文件中保存更改,程序就会更改 这对于小的更改非常有效,除了我不能在不关闭应用程序并重新编译的情况下更改代码中的状态类型 如何解决表达式问题并使状态的数据类型能够更改 而不会导致重新编译 附言。 这是密码。 我本来不想发帖,因为它真的很乱,而且很快就被砍掉了,但是人们想要它,这样他们就可以得到它 首先是显示器和空闲模块(这是一个快速破解,所以我不知道如
\state -> do
counter <- readIORef state
writeIORef state ((counter + 1)`mod`3)
postRedisplay Nothing
\state->do
柜台出租
立方体w=do
renderPrimitive Quads$do
顶点$Vertex3 w
顶点$Vertex3 w(-w)
顶点$Vertex3 w(-w)-w
顶点$Vertex3 w(-w)w
顶点$Vertex3 w
顶点$Vertex3 w(-w)
顶点$Vertex3(-w)w(-w)
顶点$Vertex3(-w)w
顶点$Vertex3 w
顶点$Vertex3 w(-w)w
顶点$Vertex3(-w)-w
顶点$Vertex3(-w)w
顶点$Vertex3(-w)w
顶点$Vertex3(-w)w(-w)
顶点$Vertex3(-w)-w(-w)
顶点$Vertex3(-w)-w
顶点$Vertex3 w(-w)w
顶点$Vertex3 w(-w)-w
顶点$Vertex3(-w)-w(-w)
顶点$Vertex3(-w)-w
顶点$Vertex3 w(-w)
顶点$Vertex3 w(-w)-w
顶点$Vertex3(-w)-w(-w)
顶点$Vertex3(-w)w(-w)
点数::整数->[(GLfloat,GLfloat,GLfloat)]
图中的点n'=设n=from积分n'(\k->设t=2*pi*k/n in(sin(t),cos(t),0.0))[1..n]
在做
清除[颜色缓冲区]
计数器保存矩阵$do
颜色$Color3((x+1.0)/2.0)((y+1.0)/2.0)((z+1.0)/2.0)
平移$Vector3 x y z
立方体(0.3::GLfloat)
)$points(9+计数器)
脸红
主模块
module Main where
import Control.Monad
import Data.Typeable as Typeable
import System.IO
import Data.IORef
import Graphics.Rendering.OpenGL
import Graphics.UI.GLUT
import Language.Haskell.Interpreter
main :: IO ()
main = do
(_, _) <- getArgsAndInitialize
createWindow "Hello World"
action <- newIORef $ do
clear [ ColorBuffer ]
flush
let imports = ["Prelude", "Data.IORef", "Graphics.Rendering.OpenGL", "Graphics.UI.GLUT"]
let modules = ["State"]
runFile (undefined :: IORef Integer -> IO ()) "Display.hs" imports $ \displayCode ->
runFile (undefined :: IORef Integer -> IO ()) "Idle.hs" imports $ \idleCode -> do
state <- newIORef 12
displayCallback $= display displayCode state
idleCallback $= Just (idle displayCode idleCode state)
mainLoop
display displayCode state = do
f <- execute displayCode
f state
idle displayCode idleCode state = do
update displayCode
update idleCode
f <- execute idleCode
f state
instance Eq GhcError where
GhcError s == GhcError t = s == t
instance Eq InterpreterError where
UnknownError s == UnknownError t = s == t
WontCompile s == WontCompile t = s == t
NotAllowed s == NotAllowed t = s == t
GhcException s == GhcException t = s == t
data V a = V {
update :: IO (),
execute :: IO a
}
runFile :: Typeable a => a -> String -> [String] -> (V a -> IO ()) -> IO ()
runFile theType file imports f = do
currentError <- newIORef Nothing
currentAction <- newIORef Nothing
let v = V {
update = do
fileContents <- readFile file
result <- runInterpreter $ do
setImports imports
interpret fileContents theType
oldError <- readIORef currentError
case result of
Right newAction -> do
when (oldError /= Nothing) $ do
writeIORef currentError Nothing
putStrLn (file ++ " Ok!")
writeIORef currentAction (Just newAction)
Left newError -> do
when ((Just newError) /= oldError) $ do
writeIORef currentError (Just newError)
print newError
, execute = do
action <- readIORef currentAction
case action of
Nothing -> do
err <- readIORef currentError
return (error (show err))
Just act -> return act
}
update v
f v
modulemain其中
进口管制
导入数据。可键入为可键入
导入系统.IO
导入数据.IORef
导入Graphics.Rendering.OpenGL
导入Graphics.UI.GLUT
导入Language.Haskell.Interpreter
main::IO()
main=do
(_, _)
运行文件(未定义::IORef Integer->IO())“Idle.hs”导入$\idleCode->do
状态[String]->(va->IO())->IO()
运行文件类型文件导入f=do
currentError我很确定这在GHC中是不可能的。在编译Haskell时,更高级的语言被分解成核心,核心也是类型化的。GHC将不会启动到核心的转换,直到程序被检查。这也是有原因的:当程序类型检查时,它同时证明了自己。正如jberryman所指出的,唯一的解决办法是为State
提供一个灵活的类型,该类型允许多态性,因此类型更改可能不会注册为多态性 根据布雷特·维克托的讲话行事,获得+1分。如果你能把你的代码发布到某个地方,那就太好了。我认为静态类型检查语言不太适合这样的环境。如果坚持使用静态类型,那么运行时(至少是调试开发运行时)应该抛弃静态类型,使用动态类型。我不确定Haskell是否存在这样的运行时。@user990666您可以发布演讲的链接吗?@Matt Fenwick代码不太有效。。。main.hs的第28行至少有语法错误。但这个想法或多或少是清楚的。目前无法观看视频,但您是否可以使用状态
类型的,这会解决您的问题吗?
module Main where
import Control.Monad
import Data.Typeable as Typeable
import System.IO
import Data.IORef
import Graphics.Rendering.OpenGL
import Graphics.UI.GLUT
import Language.Haskell.Interpreter
main :: IO ()
main = do
(_, _) <- getArgsAndInitialize
createWindow "Hello World"
action <- newIORef $ do
clear [ ColorBuffer ]
flush
let imports = ["Prelude", "Data.IORef", "Graphics.Rendering.OpenGL", "Graphics.UI.GLUT"]
let modules = ["State"]
runFile (undefined :: IORef Integer -> IO ()) "Display.hs" imports $ \displayCode ->
runFile (undefined :: IORef Integer -> IO ()) "Idle.hs" imports $ \idleCode -> do
state <- newIORef 12
displayCallback $= display displayCode state
idleCallback $= Just (idle displayCode idleCode state)
mainLoop
display displayCode state = do
f <- execute displayCode
f state
idle displayCode idleCode state = do
update displayCode
update idleCode
f <- execute idleCode
f state
instance Eq GhcError where
GhcError s == GhcError t = s == t
instance Eq InterpreterError where
UnknownError s == UnknownError t = s == t
WontCompile s == WontCompile t = s == t
NotAllowed s == NotAllowed t = s == t
GhcException s == GhcException t = s == t
data V a = V {
update :: IO (),
execute :: IO a
}
runFile :: Typeable a => a -> String -> [String] -> (V a -> IO ()) -> IO ()
runFile theType file imports f = do
currentError <- newIORef Nothing
currentAction <- newIORef Nothing
let v = V {
update = do
fileContents <- readFile file
result <- runInterpreter $ do
setImports imports
interpret fileContents theType
oldError <- readIORef currentError
case result of
Right newAction -> do
when (oldError /= Nothing) $ do
writeIORef currentError Nothing
putStrLn (file ++ " Ok!")
writeIORef currentAction (Just newAction)
Left newError -> do
when ((Just newError) /= oldError) $ do
writeIORef currentError (Just newError)
print newError
, execute = do
action <- readIORef currentAction
case action of
Nothing -> do
err <- readIORef currentError
return (error (show err))
Just act -> return act
}
update v
f v