标签: do-notation

仅使用monadic绑定语法表示阻止

据我所知,doHaskell中的块只是monadic绑定运算符的某种语法糖.例如,一个人可以转换

main = do f <- readFile "foo.txt"
          print f
          print "Finished"
Run Code Online (Sandbox Code Playgroud)

main = readFile "foo.txt" >>= print >> print "Finished"
Run Code Online (Sandbox Code Playgroud)

是否可以将所有do块转换为绑定语法?例如,f多次使用此块的情况如何:

main = do f <- readFile "foo.txt"
          print $ "prefix " ++ f
          print $ f ++ " postfix"
Run Code Online (Sandbox Code Playgroud)

假设我们在IO monad中,则不可能简单地执行readFile两次计算.如何使用绑定语法表示此示例(如果可能的话)?

我认为使用Control.Monad不是解决方案,因为它在内部使用do块.

我认为可以使用箭头(使用&&&)表达这一点- 也许这只是一个箭头可以用作monads的推广的情况

请注意,这个问题不是关于上面的特殊示例,而是关于在monadic表达式中多次使用计算结果的一般情况print.

monads haskell scope do-notation

5
推荐指数
2
解决办法
228
查看次数

这个getRight怎么样:: ab - >也许b工作?

HaskellWiki的Do notation被认为有害,部分有用的应用程序,我发现:

应该提到的是,你有时会承担起写无聊事情的负担.

例如

getRight :: Either a b -> Maybe b
getRight y =
   do Right x <- y
      return x
Run Code Online (Sandbox Code Playgroud)

一个case关于y的包括,要求如果y是不是一种权利(即左)失败,并且因此恢复在这种情况下没有.

在模式不匹配上调用fail(Nothing)听起来很有趣,所以我想尝试一下.但是,语法看起来不对 - 我们不是Eithermonad,所以我们如何从中提取任何东西y

事实上,我试过,它给了我" 无法匹配类型'要么'与'可能''.所以让我们使用正确的模式匹配器,let在这里:

getRight y = do { let (Right x) = y; return x }
Run Code Online (Sandbox Code Playgroud)

这给了我一个语法错误" 输入错误解析}} ".不是我理解为什么这不起作用,而是让我们用多行符号写出来:

getRight y = do
    let (Right x) = y
    return x
Run Code Online (Sandbox Code Playgroud)

啊,这似乎工作 - 至少解析.然而:

*Main> getRight …
Run Code Online (Sandbox Code Playgroud)

haskell pattern-matching do-notation

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

Haskell中的main函数总是以main = do开头吗?

在java中我们总是写:

public static void main(String[] args){...}
Run Code Online (Sandbox Code Playgroud)

当我们想要开始编写程序时.

我的问题是,对于Haskell,IE是否相同:我是否总是可以确定声明:main = do,当我想在Haskell中为程序编写代码时?

例如:

main = do  
    putStrLn "What's your name?"  
    name <- getLine 
    putStrLn ("Hello " ++ name) 
Run Code Online (Sandbox Code Playgroud)

该程序将询问用户"你叫什么名字?" 然后,用户输入将存储在name-variable中,并且在程序终止之前将显示"Hello"++名称.

haskell program-entry-point do-notation

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

在Haskell标记中生成唯一值

为了生成x86汇编代码,我定义了一个名为的自定义类型X86:

data X86 a = X86 { code :: String, counter :: Integer, value :: (X86 a -> a) }
Run Code Online (Sandbox Code Playgroud)

此类型用于如下所示的标记.这样可以轻松编写用于生成if语句,for循环等的模板...

generateCode :: X86 ()
generateCode = do
  label1 <- allocateUniqueLabel
  label2 <- allocateUniqueLabel
  jmp label1
  label label1
  jmp label2
  label label2
Run Code Online (Sandbox Code Playgroud)

说明定义如下:

jmp :: String -> X86 ()
jmp l = X86 { code = "jmp " ++ l ++ ";\n", counter = 0, value = const () }

label :: String -> X86 ()
label l …
Run Code Online (Sandbox Code Playgroud)

monads haskell state-monad do-notation

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

为什么“ let”语句强制“ applyative do”块要求monad约束?

考虑以下示例:

{-# language ApplicativeDo #-}

module X where

data Tuple a b = Tuple a b deriving Show

instance Functor (Tuple a) where
    fmap f (Tuple x y) = Tuple x (f y)

instance Foldable (Tuple a) where
    foldr f z (Tuple _ y) = f y z

instance Traversable (Tuple a) where
    traverse f (Tuple x y) = do
        y' <- f y
        let t' = Tuple x y'
        return $ t'
Run Code Online (Sandbox Code Playgroud)

看起来不错!但不是:

[1 of 1] Compiling X                ( …
Run Code Online (Sandbox Code Playgroud)

monads haskell ghc do-notation applicative

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

如何在where子句中使用do块赋值行中的变量?

我有以下代码示例:

{-# LANGUAGE ScopedTypeVariables #-}

main = do
  putStrLn "Please input a number a: "
  a :: Int  <- readLn
  print a

  putStrLn "Please input a number b: "
  b :: Int  <- readLn
  print b

  putStrLn ("a+b+b^2:" ++ (show $ a+b+c))
    where c = b^2
Run Code Online (Sandbox Code Playgroud)

由于某种原因,我不能bwhere子句中使用变量,我得到的错误如下:

Main3.hs:13:15: error: Variable not in scope: b
   |
13 |     where c = b^2
   |               ^
Run Code Online (Sandbox Code Playgroud)

任何想法如何bwhere条款中提供?

monads haskell scope where-clause do-notation

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

Haskell IF Else

input <- readLn
 if (input == 0)
 then 
  putStr  "0" 
 else if (input ==1)
then 
  putStr  "1" 
else if (input ==2)
Run Code Online (Sandbox Code Playgroud)

在这种情况下如何使用多个putStr在一个thenelse if

当我尝试收到错误

Type error in application
*** Expression     : putStr "0" putStr "0"
*** Term           : putStr
*** Type           : String -> IO ()
*** Does not match : a -> b -> c -> d
Run Code Online (Sandbox Code Playgroud)

monads haskell if-statement do-notation

4
推荐指数
3
解决办法
5086
查看次数

这个Haskell let-in缩进有什么问题?

在下面的Haskell代码中,我得到一个错误"输入中的解析错误".从我读过的,我用过的缩进应该没问题.事实上,我在代码的其他地方使用'let'和'in'进行了类似的缩进('let'与'in'对齐).我打破了什么规则会导致这个'in'出现问题?如果我在'in'前面添加一个空格(使其比'let'更加一个空格),它编译得很好.

runTests :: IO ()
runTests = do
             let results = fmap testLispExpr testLispText
                 resultStrings = fmap show results
                 putSeq (x:xs) = do putStrLn x
                                    putSeq xs
                 putSeq [] = return ()
             in putSeq resultStrings
Run Code Online (Sandbox Code Playgroud)

所有帮助表示赞赏.提前致谢.

syntax haskell indentation let do-notation

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

这种语法是否与表示法一样具有表现力?

do标记允许我们表达单子代码没有压倒嵌套,使

main = getLine >>= \ a -> 
       getLine >>= \ b ->
       putStrLn (a ++ b)
Run Code Online (Sandbox Code Playgroud)

可以表达为

main = do
  a <- getLine
  b <- getLine
  putStrLn (a ++ b)
Run Code Online (Sandbox Code Playgroud)

但是,假设语法允许... #expression ...代表do { x <- expression; return (... x ...) }.例如,foo = f a #(b 1) c将被贬低为:foo = do { x <- b 1; return (f a x c) }.上面的代码可以表示为:

main = let a = #getLine in
       let …
Run Code Online (Sandbox Code Playgroud)

syntax haskell do-notation

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

如何在Haskell中使用IO Double作为常规Double

我必须遵循代码

isInCircle::Double->Double->Bool
isInCircle p1 p2 = sqrt((p1*p1)+(p2*p2)) <= 1
Run Code Online (Sandbox Code Playgroud)

当我打电话的时候

isInCircle (random :: Double) (random :: Double)
Run Code Online (Sandbox Code Playgroud)

我收到这个错误

* Couldn't match expected type `Double' with actual type `g0 -> (a0, g0)'
Run Code Online (Sandbox Code Playgroud)

如果我将isInCircle函数的参数更改为IO Double我得到错误sqrt并添加...

你能帮助我吗?我的代码:

import System.Random 
main :: IO () 
main = do 
    if isInCircle (random :: Double) (random :: Double) 
    then print "True" 
    else print "False" 

isInCircle::Double->Double->Bool 
isInCircle p1 p2 = sqrt((p1*p1)+(p2*p2)) <= 1
Run Code Online (Sandbox Code Playgroud)

random io monads haskell do-notation

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