我想知道什么可以被视为关于Statemonad 的最佳实践.我也对任何其他建议持开放态度.
我有一个要解析的二进制文件.它包含需要解析的不同标头,以便能够读取整个文件.
因此,只能使用解析中的State来解析头文件.
data ParseState = ParseState {
offset :: Int64
buffer :: B.ByteString
endianness :: Endianness
pointerSize :: MachineWord
positionStack :: [Int64]
}
Run Code Online (Sandbox Code Playgroud)
然后将该数据用于Statemonad中
type Parser a = State ParseState a
Run Code Online (Sandbox Code Playgroud)
这可以完美地解决标头的解析.但是,只要我想解析整个文件,我需要标题中的信息才能正确读取文件.
data Header = Header {
txtOffset :: Int64,
stringOffset :: Int64
}
Run Code Online (Sandbox Code Playgroud)
我需要标头信息来继续解析文件.
我的想法是使用一个位于前一个状态之上的新状态monad.所以我有一个新的StateT monad:
type ParserFullState a = StateT Header (State ParserState) a
Run Code Online (Sandbox Code Playgroud)
因此,我可以继续使用新的状态转换器构建一整套解析器函数.我也可以采用不同的方式将标题添加到原始ParseState数据中.
我可以看到将标题添加回ParserState以下内容的优点如下:
lift来访问解析器原语.我能看到的缺点是:
你的建议是什么?我应该使用状态转换器吗?我应该将标头添加到原始状态还是其他任何情况?
谢谢.
我正在尝试理解这段代码:
search_bst :: Tree -> String -> Maybe Int
search_bst Leaf _ = Nothing
search_bst (Node k v l r) sk =
if sk == k then Just v
else if sk < k then search_bst l sk
else search_bst r sk
Run Code Online (Sandbox Code Playgroud)
我可以得到这个概念但是Node k v l r意味着什么?这是否意味着search_bst需要两个参数,第一个是类型的实例Node并且有三个值?
我有一个问题,实现一个可能类型列表操作!
我需要做的是:
ljoin [(2,"S"),(1,"J")] [(2,1),(2,2),(3,4)]
outputs: [(2,"S",Just 1),(2,"S",Just 2),(1,"J",Nothing)]
Run Code Online (Sandbox Code Playgroud)
到目前为止我写的:
ljoin :: Eq a => [(a,b)] -> [(a,c)] -> [(a,b,Maybe c)]
ljoin xs ys = [if xs==ys then (xa, xb, Just yc) else (xa, xb, Nothing) | (xa, xb) <- xs, (ya, yc) <- ys]
Run Code Online (Sandbox Code Playgroud)
哪会产生错误:
Inferred type is not general enough
*** Expression : ljoin
*** Expected type : Eq a => [(a,b)] -> [(a,c)] -> [(a,b,Maybe c)]
*** Inferred type : Eq a => [(a,b)] -> [(a,b)] -> …Run Code Online (Sandbox Code Playgroud) 这是代码:
main :: IO()
main = do
{
putStrLn ("Meniu: ");
putStrLn ("1. menu 1");
putStrLn ("2. menu 2");
putStrLn ("3. menu 3");
putStrLn ("4. menu 4");
putStrLn ("5. Exit - Iesire)");
putStrLn ("-------------------------");
putStr ("Enter option: ");
opt <- getLine;
if(opt == "1") then do
{
Code one etc
main
}
else if(opt == "2") then do
{
Code 2 etc
main
}
else if(opt == "3") then do
{
code 3 etc
main
}
else if(opt == "4") …Run Code Online (Sandbox Code Playgroud) 所以,我已经定义了lambda数据类型:
data LExpr
= Variable String -- variable
| Apply LExpr LExpr -- function application
| Lambda String LExpr -- Lambda abstraction
deriving (Eq, Show)
Run Code Online (Sandbox Code Playgroud)
现在我想实现Show自己的一个实例.我已经完成了show'大部分工作的功能,但没有使用实例:
show' :: LExpr -> String
show' (Variable a) = a
show' (Apply e1 e2) = "(" ++ show' e1 ++ " " ++ show' e2 ++ ")"
show' (Lambda x e) = "(? " ++ x ++ ". " ++ show' e ++ ")"
Run Code Online (Sandbox Code Playgroud)
我如何实现它,以获得以下输出而不使用显式show'函数:
Main> (Apply (Lambda …Run Code Online (Sandbox Code Playgroud) 在哈斯克尔,我可以做
Prelude> [(y*3, y+4) | x<-[0..5], let y=x^2]
[(0,4),(3,5),(12,8),(27,13),(48,20),(75,29)]
Run Code Online (Sandbox Code Playgroud)
Python 中的等效项是什么,无需重复幂运算,正如我需要的那样
>>> [((x**2)*3, (x**2)+4) for x in range(5)]
[(0, 4), (3, 5), (12, 8), (27, 13), (48, 20)]
Run Code Online (Sandbox Code Playgroud)
我当然可以用 lambda 模拟 Haskell 代码,但这感觉不太 Pythonic...
>>> [(lambda y: (y*3, y+4))(x**2) for x in range(5)]
Run Code Online (Sandbox Code Playgroud) 我是Haskell的初学者,试用GPipe.
以下代码运行正常:
shader <- compileShader $ do
primitiveStream <- toPrimitiveStream id
let transPrims = fmap
(\(pos,col) -> (perspective (pi/3) 1 1 100 !* pos, col))
primitiveStream
fragmentStream <- rasterize
(const (FrontAndBack, ViewPort (V2 0 0) (V2 500 500), DepthRange 0 1))
transPrims
drawContextColor (const (ContextColorOption NoBlending (V3 True True True)))
fragmentStream
Run Code Online (Sandbox Code Playgroud)
但是,我有2个变量windowWidth和windowHeight(都是Int类型),当我尝试这样做时:
shader <- compileShader $ do
primitiveStream <- toPrimitiveStream id
let transPrims = fmap
(\(pos,col)
-> (perspective (pi/3) (windowWidth/windowHeight) 1 100 !* pos, col))
primitiveStream
fragmentStream <- rasterize
(const …Run Code Online (Sandbox Code Playgroud) 有人可以解释为什么这个编译
Prelude> 1 :: Num a => a
Run Code Online (Sandbox Code Playgroud)
而这不是
Prelude> 1.0 :: Num a => a
Run Code Online (Sandbox Code Playgroud)
第二个例子可以使用Fractional,但是Num是超类Fractional.就像它的超类一样Integral.
我对函数式编程和Haskell都很陌生,所以我不确定我是否正确地提出了这个问题,或者它是否有意义,但我决定尝试,因为我没有找到任何有用的东西.我基本上试图实现一个可以返回a Int,a String或List 的函数.我知道我可以用它Either来返回两种类型中的一种,但我想返回三种或更多种中的一种.我尝试定义一个新类型,但我卡住了.
data Rets = Int | String | Bool
checkInt :: Rets -> Bool
check x = case x of
Int x -> True
Run Code Online (Sandbox Code Playgroud)
checkInt应该返回,True如果给出Int,它只是为了测试,但无论如何我包括它.
我知道我的问题很乱,所以我会感谢任何解释.提前致谢!
我编写了一个程序,结果使用列表太慢了,所以我尝试切换到序列。但是,在查看文档后我似乎无法找出正确的语法。
\n\n到目前为止,我正在尝试使用这个简单的代码来学习:
\n\nimport Control.Monad\nimport qualified Data.Sequence as S\n\nmain :: IO ()\nmain = do \n let testSeq = S.empty\n testSeq S.|> 5\n testSeq S.|> 20\n testSeq S.|> 3\n let newSeq = S.update 2 3 testSeq\n let x = lookup 2 testSeq\n print x\nRun Code Online (Sandbox Code Playgroud)\n\n我已经尝试了一段时间的语法但没有运气,但它仍然有很多错误:
\n\ntest.hs:9:8:\n Couldn't match expected type \xe2\x80\x98IO a0\xe2\x80\x99\n with actual type \xe2\x80\x98S.Seq Integer\xe2\x80\x99\n In a stmt of a 'do' block: testSeq S.|> 5\n In the expression:\n do { let testSeq = S.empty;\n testSeq S.|> …Run Code Online (Sandbox Code Playgroud)