如何更改数据类型而不导致 Haskell 重新编译?

2024-02-23

看完一段视频后布雷特·维克多的演讲 http://vimeo.com/36579366,我受到启发,编写了一个快速破解程序,该程序与他在演讲中演示的开发环境有些相似。

基本上,其想法是,让应用程序在一个窗口中运行,每当在源文件中保存更改时,程序就会更改。

这对于小的更改非常有效,除了我无法在不关闭应用程序并重新编译的情况下更改代码中的状态类型。

如何解决表达问题并使我的状态的数据类型能够改变 不会导致重新编译?

附: 这是代码。 我本来不想发帖,因为它真的很乱,而且很快就被拼凑在一起了,但人们想要它,这样他们就能得到它。

首先是显示器和空闲模块(这是一个快速破解,所以我不知道如何将它们作为真正的模块来实现)。

Idle.hs

\state -> do
    counter <- readIORef state
    writeIORef state ((counter + 1)`mod`3)
    postRedisplay Nothing

显示.hs

\state -> let
cube w = do 
    renderPrimitive Quads $ do
        vertex $ Vertex3 w w w
        vertex $ Vertex3 w w (-w)
        vertex $ Vertex3 w (-w) (-w)
        vertex $ Vertex3 w (-w) w
        vertex $ Vertex3 w w w
        vertex $ Vertex3 w w (-w)
        vertex $ Vertex3 (-w) w (-w)
        vertex $ Vertex3 (-w) w w
        vertex $ Vertex3 w w w
        vertex $ Vertex3 w (-w) w
        vertex $ Vertex3 (-w) (-w) w
        vertex $ Vertex3 (-w) w w
        vertex $ Vertex3 (-w) w w
        vertex $ Vertex3 (-w) w (-w)
        vertex $ Vertex3 (-w) (-w) (-w)
        vertex $ Vertex3 (-w) (-w) w
        vertex $ Vertex3 w (-w) w
        vertex $ Vertex3 w (-w) (-w)
        vertex $ Vertex3 (-w) (-w) (-w)
        vertex $ Vertex3 (-w) (-w) w
        vertex $ Vertex3 w w (-w)
        vertex $ Vertex3 w (-w) (-w)
        vertex $ Vertex3 (-w) (-w) (-w)
        vertex $ Vertex3 (-w) w (-w)

points :: Integer -> [(GLfloat,GLfloat,GLfloat)]
points n' = let n = fromIntegral n' in map (\k -> let t = 2*pi*k/n in (sin(t),cos(t),0.0))  [1..n]

in do
    clear [ ColorBuffer ]
    counter <- readIORef state
    mapM_ (\(x,y,z) -> preservingMatrix $ do
           color $ Color3 ((x+1.0)/2.0) ((y+1.0)/2.0) ((z+1.0)/2.0)
           translate $ Vector3 x y z
           cube (0.3::GLfloat)
           ) $ points (9 + counter)
    flush

主要模块

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

我很确定这在 GHC 中是不可能的。当Haskell编译时,高级语言被脱糖到Core中,Core也是类型化的。在程序经过类型检查之前,GHC 不会启动向 Core 的转换。这也是有原因的:当程序类型检查时,它同时证明了自己。正如 jberryman 所指出的,唯一的解决办法是为State这将允许多态性,因此类型更改可能不会注册为一个。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何更改数据类型而不导致 Haskell 重新编译? 的相关文章

  • 未确定的泛型类型在 ghci 的运行时中如何表示

    我很清楚通用函数和通用数据类型 在泛型类型中 data SB forall x show x gt SB x instance Show SB where show SB x show x 所以对于任何给定类型x 如果它有一个签名Show
  • 如何为 GHCi 设置程序的命令行参数?

    假设某个 Haskell 文件被执行 runghc Queens hs gecode compile 现在 这失败了 我想用它来调试它ghci 我如何传递选项gecode compile进入程序 所以getArgs会正确读取吗 Thanks
  • Haskell 将两个列表中不同索引处的元素组合起来

    对这个糟糕的标题表示歉意 我不太确定如何用语言描述它 但这就是我的意思 如果您知道更好的表达方式 请告诉我 假设我有 2 个长度相等的列表 a b c x y z 我想创建列表 a y z b x z c x y 本质上 对于 list1
  • 尝试以特殊行为渲染 Threepenny-gui 中的字段

    我想要做的是设置字段 当它们处于焦点时显示详细信息 而当它们不处于焦点时显示摘要 例如 A 当它失去焦点 变得模糊 时 我将值保存在 状态 映射中 然后将该值更改为旧值的函数 即汇总值 b 当它获得焦点时 我用我在地图中保存的旧值替换摘要值
  • 用户状态(秒差距)

    我正在使用秒差距解析一个表达式 并且我想使用秒差距中的用户状态来跟踪这些表达式中的变量 不幸的是我真的不知道该怎么做 给出以下代码 import Data Set as Set inp x y z data Var V String var
  • 通过列表搜索

    我一直在尝试定义一个函数 给定一个整数列表和一个整数 n 返回一个布尔值 指示 n 是否在列表中恰好出现一次 我有这个 但它不起作用 我无法弄清楚 once a gt a gt Bool gt Bool filter filter p x
  • 应该如何理解“引理”函数的一般类型?

    也许这是一个愚蠢的问题 这是引用自the 哈索主义 paper https personal cis strath ac uk conor mcbride pub hasochism pdf 解决这个问题的一种方法是对引理进行编码 由下式给
  • Haskell FFI - 你能从 Haskell 数据结构中获取 C 指针吗?

    我有很多 C 结构体 结构如下 typedef struct unsigned int a unsigned int b StructA 还有很多功能 比如 void doSomethingWith StructA StructB Stru
  • 仅使用 Hunit 在 Haskell 中创建并运行最小测试套件

    我对 Haskell 比较陌生 所以如果我的术语不太正确 请提前道歉 我想为一个非常简单的项目实现一些简单的单元测试 通过管理cabal 我注意到这个非常相似的问题 https stackoverflow com questions 118
  • macOS 上的堆栈构建

    我是新来的haskell 我有最简单的程序 usr bin env stack stack resolver lts 13 7 script module Main where import Lib main IO main putStrL
  • 为什么 Haskell 类型签名声明有多个箭头?

    抱歉 这句话措辞不好 但很难描述 我想我会跳到这个例子 add Integer gt Integer gt Integer add x y x y 为什么 Integer gt Integer gt Integer 代替 Integer I
  • 运营商部分应用

    如果我想在字符末尾添加一个空格以返回列表 如果我不传递任何参数 我将如何通过部分应用程序来完成此操作 还有类型是 space Char gt Char 由于使用 和 运算符出现 解析错误 我在末尾添加空格时遇到问题 到目前为止我所拥有的是
  • Foldl 是否比其严格的表亲 Foldl' 更好?

    Haskell 有两个列表左折叠函数 foldl 以及 严格 版本 foldl 不严格的问题foldl是它建造了一座重击塔 foldl 0 1 5 gt 0 1 2 3 4 5 gt 15 这会浪费内存 并且如果列表中的项太多 可能会导致堆
  • 移动列表中特定元素的简单函数

    我是 Haskell 的新手 我正在尝试弄清楚如何创建一个函数 shift Eq a gt a gt a gt Int gt a shift x h t z 输入 一个通用列表和一个相同类型的元素 x 前提条件 元素x存在于列表中 Outp
  • Haskell:Where 与 Let

    我是 Haskell 的新手 我很困惑Where vs Let 它们似乎都提供了相似的目的 我读过一些比较Where vs Let但我很难辨别何时使用它们 有人可以提供一些背景信息或者一些示例来说明何时使用其中一种而不是另一种吗 哪里与让
  • Haskell/GHC:使用相同模式匹配多个一元构造函数

    所以我正在尝试定义 TrieSet 数据类型 尽管我知道我不需要 http hackage haskell org package TrieMap module Temp where import Data Map data TrieSet
  • 在 Haskell 中将字节转换为 Int64s/Floats/Doubles

    我正在尝试解析 Haskell 中的二进制文件格式 Apple 的二进制属性列表格式 该格式所需的内容之一是将字节序列视为 a 无符号 1 2 或 4 字节整数 b 有符号 8 字节整数 c 32 位floats d 64 位doubles
  • 生成所有可能的树

    给定以下数据类型定义 data FormTree Empty Node FormTree FormTree deriving Show 我想编写一个函数 它生成一个无限列表 其中包含按长度排序的所有可能的树 例如节点数量 下面的代码几乎满足
  • Haskell Cabal 包 - 找不到 Paths_ 模块

    我正在开发一个 Haskell 项目 Happstack 服务器 Blaze HTML 前端作为主要库 我想添加一个静态数据目录 看起来你可以使用 Cabal 使用自动生成的Path
  • 访问函数中的环境

    In main我可以读取我的配置文件 并将其提供为runReader somefunc myEnv正好 但somefunc不需要访问myEnv读者提供 链中的下一对也没有提供 需要 myEnv 中某些内容的函数是一个微小的叶函数 如何在不将

随机推荐

  • 检测存在哪些 Unicode 字形?

    JavaScript CSS web 中有没有办法检测系统是否具有某个 Unicode 字符的有效字形 例如 我想检测某种语言中的某个字符是否显示为方框 因为用户没有显示这些 Unicode 点的字体 或者他们是否确实会看到这些字符 这里描
  • 属性与实例变量[重复]

    这个问题在这里已经有答案了 可能的重复 Objective c cocoa cocoa touch 中的 实例变量 和 属性 之间有区别吗 https stackoverflow com questions 843632 is there
  • 如何为 asp.net 身份创建安全标记值 (IUserSecurityStampStore)

    在我的 MVC 5 应用程序中 我必须手动创建安全标记值 身份团队当前的实现似乎使用了指南 Guid NewGuid ToString D 我自己创建一个新的 Guid 来用作新的安全标记值是否安全 或者这是否会在将来的 ASP NET 身
  • Mongo PHP 驱动程序 1.2.10 与 MAMP

    我正在尝试让最新的 Mongo 驱动程序与 OS X 10 5 8 上的 MAMP 1 9 6 一起使用 我从源代码成功构建了它 因为似乎没有预编译版本 将其包含到正确的目录中并重新启动了 apache 但 PHP 无法识别该扩展名 我之前
  • CSS:发光文本,发光非常宽和高

    几天以来我一直在研究 box shadow 和 text shadow 我正在努力获得以下效果 我想要从文字中散发出光芒 a 一度盘旋 很简单 这应该很容易 因为我探索了使用文本阴影 好的 但它适用于小发光 我的意思是 一旦发光较大 由于其
  • Eclipse 在接口方法签名中生成无用的“公共抽象”修饰符

    在使用 Eclipse 重构工具提取方法时 有没有办法阻止生成无用的内容public abstract接口方法签名中的修饰符 谢谢阿列克谢 这听起来像是一个 Eclipse 错误 但它有一个解决方法 该错误自 2004 年 8 月 9 日起
  • CFHTTPMessageAddAuthentication 无法向请求添加身份验证数据

    我正在尝试扩展功能SocketRocket https github com square SocketRocket图书馆 我想添加身份验证功能 由于该库正在使用CFNetwork CFHTTPMessage API https devel
  • 如何在离线服务器上安装 npm -g

    我需要在离线服务器上安装 全局 npm 应用程序 安装普通应用程序很容易 npm install 然后打包生成的文件 手动或使用npm pack 但是 如何安装全局应用程序 具有某种安装脚本 例如forever没有互联网 npm insta
  • 在同一个 R markdown 页面中应用多列划分

    我想如图所示分割我的 Rmarkdown 文档 第一部分为一列 其他部分为两列 used onecolumn and twocolumn但每个部分都是在单个页面中创建的 有解决办法吗 This article https journals
  • 如何在jquery中获取tinymce内容?

    我正在尝试获取tinymce数据 但收到tinyMCE未定义错误 这是我的代码 function savePost console log jQuery wp tinymce editor tinyMCE getContent 请检查 Ti
  • 使用 knockout js 和 jquery ui 滑块

    我试图弄清楚knockout js是否可以很好地解决以下问题 我有多个滑块想要链接到文本框 当文本框更改时 相应的滑块必须更新为新值 反之亦然 更改滑块值或文本框时 需要调用一个函数 该函数使用所有文本框的输入来计算结果 我有我的快速但肮脏
  • 从 Google App Engine (Java) 将文件上传到 Google 云存储

    如何将文件从谷歌应用程序引擎中的servlet上传到谷歌云存储 当我这样做时 Google 云存储不知道文件的类型 即我从 HTML 表单发送的文件 编写 HTML JavaScript 和 servlet 将文件上传到云存储的正确方法是什
  • v-dialog Vuetify 的自定义位置

    我需要在页面右下角打开一个具有一定宽度和高度的 v 对话框 但是 我不明白该怎么做 V dialog总是在页面居中 我搜索了官方文档 尝试使用CSS 但无法 有任何想法吗 Note 其他提供的解决方案并不令人满意 因为它们搞乱了转换 或者我
  • 使用exist()的Cloud firestore规则是否算作读取?

    我正在存储被阻止用户的文档集合 我通过检查电子邮件是否存在于被阻止的集合中来检查请求是否来自被阻止的用户 allow read if exists databases database documents blocked request a
  • 如何将当前cygwin目录转换为windows格式

    显示我正在使用的当前目录 pwd在 Cygwin 中运行良好 This document https cygwin com cygwin ug net using effectively html正在解释如何将 cygwin 目录转换为 w
  • 存储库是单例还是静态还是都不是?

    我有一个 ASP NET 网站 它使用域驱动设计并使用存储库进行数据库操作 我想知道单例存储库和静态存储库以及每次访问都会新增的简单存储库类的优缺点是什么 此外 如果有人可以比较并指导我使用其中的哪一个 我将不胜感激 静态和单例对于存储库模
  • Jquery 验证错误放置(单选按钮)

    我正在尝试使用 Jquery 验证插件来验证我的表单 我的大多数输入元素的右侧都会出现错误消息 但单选按钮只会给我带来麻烦 如果我没有给出 div group 类的宽度 错误消息会出现在整个页面的外部 因为我假设 div 宽度是页面的 10
  • 安装 Shield LE - 错误 6058 ...在 64 位中合并 Visual C++ 10.0 CRT

    我正在尝试编译一个安装屏蔽项目 这是一个 64 位程序 我不断收到此错误 尽管它确实编译正常并安装正常 Error 16 6058 Error merging Visual C 10 0 CRT IA64 with module ID C
  • 有没有办法在 swift 中从 utf16 数组创建字符串?

    我们知道 String utf16 提供代码单元或 String unicodeScalars 提供标量 如果我们通过删除一些元素等来操作 codeunits 和 unicodeScales 有没有办法构造回结果字符串 Swift 2 1
  • 如何更改数据类型而不导致 Haskell 重新编译?

    看完一段视频后布雷特 维克多的演讲 http vimeo com 36579366 我受到启发 编写了一个快速破解程序 该程序与他在演讲中演示的开发环境有些相似 基本上 其想法是 让应用程序在一个窗口中运行 每当在源文件中保存更改时 程序就