据我所知,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.
在HaskellWiki的Do notation被认为有害,部分有用的应用程序,我发现:
应该提到的是,你有时会承担起写无聊事情的负担.
例如
Run Code Online (Sandbox Code Playgroud)getRight :: Either a b -> Maybe b getRight y = do Right x <- y return x一个
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) 在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"++名称.
为了生成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) 考虑以下示例:
{-# 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) 我有以下代码示例:
{-# 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)
由于某种原因,我不能b在where子句中使用变量,我得到的错误如下:
Main3.hs:13:15: error: Variable not in scope: b
|
13 | where c = b^2
| ^
Run Code Online (Sandbox Code Playgroud)
任何想法如何b在where条款中提供?
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在一个then或else 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) 在下面的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)
所有帮助表示赞赏.提前致谢.
该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) 我必须遵循代码
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) do-notation ×10
haskell ×10
monads ×6
scope ×2
syntax ×2
applicative ×1
ghc ×1
if-statement ×1
indentation ×1
io ×1
let ×1
random ×1
state-monad ×1
where-clause ×1