标签: do-notation

'做'在Haskell构建

我正在尝试学习Haskell,并希望编写一个小程序,将文件内容打印到屏幕上.当我将其加载到GHCi时,我收到以下错误:

'do'结构中的最后一个语句必须是表达式

我知道这个问题已经在这里被提出了:Haskell - "'do'结构中的最后一个语句必须是一个表达式".

即使我的代码非常相似,我仍然无法弄清楚问题.如果有人能指出我的问题,我会非常感激.

module Main (main) where

import System.IO
import System(getArgs)

main :: IO()
main = do
    args <- getArgs
    inh <- openFile $ ReadMode head args
    printFile inh
    hClose inh

printFile :: Handle -> IO ()
printFile handle = do
    end <- hIsEOF handle
        if end
            then return ()
            else do line <- hGetLine handle
                putStrLn line
                printFile handle
Run Code Online (Sandbox Code Playgroud)

io syntax monads haskell do-notation

1
推荐指数
1
解决办法
1077
查看次数

理解符号和绑定

我是haskell的新手,我正在尝试理解本文档中用于创建Monadic解析器的方法https://www.cs.nott.ac.uk/~gmh/pearl.pdf

我没有完全遵循它,而是试图以不同的方式做到这一点,以便正确理解它,因此,我最终得到了这段代码

newtype Parser a = Parser (String -> Maybe (a, String))

item :: Parser Char
item = Parser (\cs -> case cs of
            "" -> Nothing
            (c:cs) -> Just (c, cs))

getParser (Parser x) = x

instance Monad Parser where
    return x = Parser (\cs -> Just (x,cs))
    (Parser p) >>= f  = Parser (\cs -> let result = p cs in
                  case result of
                    Nothing -> Nothing
                    Just (c,cs') -> getParser (f c) cs')

takeThreeDropSecond :: Parser …
Run Code Online (Sandbox Code Playgroud)

monads haskell do-notation

1
推荐指数
1
解决办法
134
查看次数

将函数应用程序的结果存储在DO块内的元组中

虽然我可以应用一个函数两次并将结果绑定到元组:


  let foo :: Num a => a -> a
      foo x = x + 1

  let (x,y) = (foo 10, foo 20)
Run Code Online (Sandbox Code Playgroud)

这不能在一个do块内完成(至少我不知道如何正确地做到这一点):


  let bar :: Num a => a -> IO a
      bar x = do
                  let y = x + 1
                  return y

  let test :: Num a => IO a
      test = do
                 (x,y) <- (bar 10, bar 20)
                 return y
Run Code Online (Sandbox Code Playgroud)

键入GHCI REPL时出现以下错误:


:29:15:
    Couldn't match expected type ‘IO a1’ with actual type ‘(t0, …
Run Code Online (Sandbox Code Playgroud)

haskell functional-programming do-notation

1
推荐指数
2
解决办法
210
查看次数

de sugaring做符号

我想用以下的符号表示糖.但我不确定我是否做得对:

方法是:

quote   = do
    time        <- qtime
    qcomma
    ask         <- double
    qcomma
    bid         <- double
    qcomma
    askVolume   <- double
    qcomma
    bidVolume   <- double
    endOfLine
    return $ Quote time ask bid askVolume bidVolume
Run Code Online (Sandbox Code Playgroud)

quote   = Quote <$> (qtime <* qcomma)
                <*> (double <* qcomma)
                <*> (double <* qcomma)
                <*> (double <* qcomma)
                <*> (double <* endOfLine)
Run Code Online (Sandbox Code Playgroud)

相当于:

qtime >>= (\time -> qcomma) 
    >> double 
        >>= (\ ask -> qcomma)  
            >> double  
                >>= (\bid -> qcomma) 
                    >> double
                        >>= (\askVolume …
Run Code Online (Sandbox Code Playgroud)

haskell do-notation applicative

1
推荐指数
1
解决办法
90
查看次数

Haskell Monads中`let .. in do`和`<-`表示法有什么区别?

我正在尝试实现一个将字符串转换为Maybe Ints列表的函数,例如readInts "1 2 42 foo" = [Just 1,Just 2,Just 42,Nothing].

我的第一个方法是:

readInts (s::String) = do {
    ws <- words s;
    return (map (readMaybe::(String -> Maybe Int)) ws)
}
Run Code Online (Sandbox Code Playgroud)

这导致以下错误:

lab_monad.hs:20:52:
    Couldn't match type ‘Char’ with ‘[Char]’
    Expected type: [String]
      Actual type: String
    In the second argument of ‘map’, namely ‘ws’
    In the first argument of ‘return’, namely
      ‘(map (readMaybe :: String -> Maybe Int) ws)’
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

我接下来(和工作)尝试的是:

readInts (s::String) = do {
    let ws …
Run Code Online (Sandbox Code Playgroud)

monads haskell compiler-errors type-mismatch do-notation

1
推荐指数
1
解决办法
103
查看次数

涉及putStrLn的谜团

为什么下面的代码会产生错误parse error on input ‘putStrLn’

main = do line <- fmap reverse getLine
   putStrLn $ "You said " ++ line ++ " backwards!"
   putStrLn $ "Yes, you said " ++ line ++ " backwards!"

<interactive>:11:4: error: parse error on input ‘putStrLn’
Run Code Online (Sandbox Code Playgroud)

另外,为什么以下代码会产生错误parse error on input ‘let’

main = do line <- getLine
  let line' = reverse line
  putStrLn $ "You said " ++ line' ++ " backwards!"
  putStrLn $ "Yes, you said " ++ line' ++ …
Run Code Online (Sandbox Code Playgroud)

haskell syntax-error do-notation io-monad

1
推荐指数
1
解决办法
179
查看次数

如何在递归函数中使用Control.Monad.Cont?

我正在提供这个问题的答案,我想到了使用Contmonad 的想法.我不知道Haskell足以解释为什么这个程序不起作用

import Control.Monad.Cont

fib1 n = runCont (slow n) id
  where
    slow 0 = return 0
    slow 1 = return 1
    slow n = do
      a <- slow (n - 1)
      b <- slow (n - 2)
      return a + b

main = do
  putStrLn $ show $ fib1 10
Run Code Online (Sandbox Code Playgroud)

错误 -

main.hs:10:18: error:
    • Occurs check: cannot construct the infinite type: a2 ~ m a2
    • In the second argument of ‘(+)’, namely ‘b’ …
Run Code Online (Sandbox Code Playgroud)

monads continuations haskell type-mismatch do-notation

1
推荐指数
1
解决办法
97
查看次数

在monad的上下文中一定要使用符号吗?

Haskell 2010年报告说

do表达式为monadic编程提供了更常规的语法。它允许一个表达式,例如

putStr "x: " >>
getLine >>= \l ->
return (words l)
Run Code Online (Sandbox Code Playgroud)

用更传统的方式写成:

do putStr "x: "
   l <- getLine
   return (words l)
Run Code Online (Sandbox Code Playgroud)

汤普森说,Haskell函数编程技巧说

我们将继续使用do表示法,但要记住,它本质上 归结为一个函数(>> =)的存在,该函数负责对I / O程序进行排序并将其结果绑定以供将来使用。

以上是否意味着必须在monad的上下文中使用符号?

如果是,为什么以下函子使用do表示法?

instance    Functor IO  where
    --  fmap    ::  (a  ->  b)  ->  IO  a   ->  IO  b
    fmap    g   mx  =   do  {x  <-  mx; return  (g  x)}
Run Code Online (Sandbox Code Playgroud)

monads haskell do-notation

1
推荐指数
1
解决办法
139
查看次数

将配置文件读入 Haskell 时发生 IO

我有用于我尚未编写的 Haskell 应用程序的输入数据,这些数据驻留在一个文件中。我不更新文件。我只需要读取文件并将其输入到需要字符串列表的 Haskell 函数中。但是读取文件当然会产生IO数据对象。我了解到使用该<-操作可以以某种方式“取出”打包在IO结构中的字符串,因此我尝试了以下尝试:

run :: [String]
run = do
  datadef_content <- readFile "play.txt" -- yields a String
  let datadef = lines datadef_content -- should be a [String]
  return datadef
Run Code Online (Sandbox Code Playgroud)

我把它放到一个文件中play.hs,然后从 ghci 加载它

:l play
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,我收到了该readFile行的错误消息

 Couldn't match type ‘IO’ with ‘[]’
 Expected type: [String]
   Actual type: IO String
Run Code Online (Sandbox Code Playgroud)

return错误信息

 Couldn't match type ‘[Char]’ with ‘Char’
 Expected type: [String]
   Actual type: [[String]]
Run Code Online (Sandbox Code Playgroud)

第一条似乎表明我无法摆脱IO,而最后一条消息似乎表明,这lines将返回一个字符串列表列表,这对我来说也没有意义。 …

io monads haskell file-read do-notation

0
推荐指数
1
解决办法
79
查看次数

Haskell:非对称嵌套 do 表示法和 let

我正在通过编写玩具语言来学习 Haskell。我想知道如何将 let 与嵌套 do 构造结合起来。我想写类似的东西(完全常见的用例,但在 do 表示法中使用 State-monad):

let x' = if special x then do ... else x
Run Code Online (Sandbox Code Playgroud)

更准确地说,我想写一些像这样的代码:

moveOpersToVirt :: [IOper] -> State (RegNum, M.Map OperNum Var, TRegs) [IOper]
moveOpersToVirt ((i, Oper op r arg1 arg2):os) = do
  (virt_rn, mp, regs) <- get
  let arg2' = if isRegGlobal arg2
      -- get previously remembered value for "global reg arg2"
      then getRegStrict regs (getValRegStrict arg2) 
      else arg2
  let arg1' = ...
  let r' = if isRegGlobal r
    -- substitute …
Run Code Online (Sandbox Code Playgroud)

haskell do-notation

0
推荐指数
1
解决办法
143
查看次数