据我所知,Haskell的ST monad是独一无二的,它允许我描述一个本地使用可变内存的计算,但仍然提供一个纯粹的接口.也就是说,它允许我改变内存,只要该突变不会逃避计算.最简单的例子就是:
runST $ newSTRef "trying to return a memory reference."
Run Code Online (Sandbox Code Playgroud)
这导致编译时错误(多酷!):
Couldn't match type ‘a’ with ‘STRef s a0’
because type variable ‘s’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context: ST s a
at <interactive>:1:1-18
Expected type: ST s a
Actual type: ST s (STRef s a0)
In the second argument of ‘($)’, namely ‘newSTRef 0’
In the expression: runST $ newSTRef 0
Run Code Online (Sandbox Code Playgroud)
我的理解是,如果允许可变引用逃脱计算,它可以在其他地方进行变异,并且我的ST计算可能不再具有纯接口(它可能在不同的调用上返回不同的值).
我的问题是:这是如何实施的?我看到runST和newSTRef的定义大量使用了RankNTypes,但是我无法理解这些类型如何产生上面的编译错误.
我有一个像下面的测试函数,用于runST内部变异状态.我go在其中定义了另一个函数,它返回Int包含在ST结果中(只是玩一些ST概念).问题是我的函数类型签名似乎是错误的.如果我注释掉函数类型签名,代码运行正常.使用注释代码中的类型签名,它不会编译,因为编译器将go函数的状态解释为与封闭范围中的状态不同.我将理解如何定义函数类型签名以将外部函数传递ST s给go函数的指针.
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Data.Word(Word32)
import Data.Vector.Unboxed as U hiding (mapM_,create)
import Control.Monad.ST as ST
import Control.Monad.Primitive (PrimState)
import System.Random.MWC
test :: Word32 -> Int
test x = runST $ do
gen <- initialize (U.singleton $ fromIntegral x :: U.Vector Word32) :: (forall s. ST s (Gen (PrimState (ST s))))
let --go :: Int -> ST s Int …Run Code Online (Sandbox Code Playgroud) 在以下代码中,X在全局容器中注册,该容器成为其共享所有者.X的析构函数测试它不再是这种所有权的一部分了,我希望它是被破坏的有效前提条件.
#include <vector>
#include <memory>
struct X {
~X();
};
std::vector<std::shared_ptr<X> > global_x_reg;
X::~X()
{
for (auto iter = global_x_reg.begin(), end = global_x_reg.end(); iter != end; ++iter)
if (iter->get() == this)
throw "Oops. X gets destroyed while it is still owned!";
}
int main(int argc, char** argv)
{
global_x_reg.push_back( std::shared_ptr<X>(new X) );
global_x_reg.clear(); // calls X::~X().
}
Run Code Online (Sandbox Code Playgroud)
当它运行时(在使用VS2010编译之后),当清除容器时抛出"Oops ...".
问题:
clear()以这样的方式实现,即在其值的破坏期间,这些值不再作为容器可见. std::shared_ptr::get在什么时候std::shared_ptr摧毁它的指针nullptr呢?定时器如何在PLC结构化文本(ST)中工作?我们如何申报?
我一直在研究PLC的标准(IEC 61131-3),他们不谈ST的计时器.我知道绝大多数PLC程序员都是在梯形逻辑中完成它们,但在这种特殊情况下,我真的需要在ST中声明定时器.
我正在使用罗克韦尔PLC.
据我了解,定义的主要目标enumerators是将变量分配给一些数字及其相等的字符串。
我们可以将 var 定义a为our或enum中的任何地方,如下所示:initializing sectionProgramFunction Block
a:(start,stop,operate);
Run Code Online (Sandbox Code Playgroud)
很难,我不知道为什么我们看不到这一点,tabular view但有一个大问题:
将枚举器定义为 DUT 有什么好处?
我试图从 PLC (Beckhoff-cx5130) 获取当前时间。我尝试过“GETSYSTEMTIME”,但没有得到任何输出。我还尝试了“NT_GetTime”“TIMESTRUCT”和“T_FILETIME”,但显示一些编译错误(可能是库问题)。关于此问题的任何建议(示例代码)将受到高度赞赏。谢谢!
与我最近关于处理大型数据块的问题密切相关,我已经达到了这样的程度,即我需要采用一个大的不可变数据块,使其对某些操作变得可变,然后在完成后再次使其变为不可变.
由于我想保留至少纯度的外观,可变数据将是原始不可变数据的可变副本.作为参考,我正在查看Real World Haskell 中的Bloom Filter示例,但发现我实际上无法使我的代码在runST中运行.
我的数据结构,首先是纯数据,然后是不纯的:
import Data.Vector.Unboxed (Vector)
import Data.Vector.Unboxed.Mutable (MVector)
data PixelMap = Bitmap Int Int (Vector Bool)
data MPixelMap s = MBitmap Int Int (MVector s Bool)
Run Code Online (Sandbox Code Playgroud)
然后我只创建一个基本的newBitmapM函数:
newBitmapM :: (Int, Int) -> ST s (MPixelMap s)
newBitmapM (width, height) = MBitmap width height `liftM` MV.replicate (width * height) False
Run Code Online (Sandbox Code Playgroud)
这加载到GHCI就好了,但后来我尝试运行它:
> runST $ newBitmapM (15, 15)
<interactive>:78:9:
Couldn't match type `a' with `PixelMapMutable s'
`a' is a rigid type variable bound …Run Code Online (Sandbox Code Playgroud) enum当你在 a 中定义 an 时出现问题method。
我试图这样做:
VAR
enumA:(A,B,C);
END_VAR
Run Code Online (Sandbox Code Playgroud)
TwinCAT3 Shell 当我在(TcXaeShell)中使用它时,编译器会做出反应。

任何帮助,将不胜感激。
我有一个想要返回值的方法。该声明对我来说很清楚。但是如何在方法实现中分配要返回的值呢?
我只能想到创建一个输出变量并使用它来将值传播给调用者。但这绝对不是我期望返回值的工作方式:
METHOD M_MyMethod : BOOL
VAR_OUT
bReturnVal : BOOL;
END_VAR
Run Code Online (Sandbox Code Playgroud)
// Do some method things here.
// Then assign the return value.
bReturnVal := bWhatever;
Run Code Online (Sandbox Code Playgroud) 这就是我现在的情况
TYPE MyType: STRUCT
name: STRING[20];
input: INT;
output: INT;
END_STRUCT
END_TYPE
Run Code Online (Sandbox Code Playgroud)
PROGRAM PLC_PRG:
VAR
struct: MyType;
struct_NULL: MyType;
error: BOOL;
END_VAR
IF error THEN
struct := struct_NULL;
END_IF
END_PROGRAM
Run Code Online (Sandbox Code Playgroud)
是否有另一种方法可以使结构无效,而无需声明和使用struct_NULL