F#Computation Expressions允许隐藏厚层语法糖背后的一元语法的复杂性.Scala中是否有类似的东西?
我认为这是为了理解......
例:
val f = for {
a <- Future(10 / 2) // 10 / 2 = 5
b <- Future(a + 1) // 5 + 1 = 6
c <- Future(a - 1) // 5 - 1 = 4
} yield b * c // 6 * 4 = 24
val result = f.get
Run Code Online (Sandbox Code Playgroud)
但它确实感觉不对.有更好的语法吗?
例如,你可以拥有哈斯克尔
main = do fromHandle <- getAndOpenFile "Copy from: " ReadMode
toHandle <- getAndOpenFile "Copy to: " WriteMode
contents <- hGetContents fromHandle … 对于所有表现良好的Monads,以下两种flatten等效实现是否相同?
flatten1 xss = do
xs <- xss
x <- xs
return x
flatten2 xss = do
xs <- xss
xs
Run Code Online (Sandbox Code Playgroud) 我读过" 了解你一个Haskell",Haskell中的列表理解可以改写为monadic join或(实际上是相同的)do-notation.
但是,当我尝试重写以下代码时(生成所有可能的列表,其中包含给定列表中的每个元素):
c :: [[a]] -> [[a]]
c [] = [[]]
c (x:xs) = [a:b | a <- x, b <- c xs]
Run Code Online (Sandbox Code Playgroud)
以这种方式:
d :: [[a]] -> [[a]]
d [] = [[]]
d (x:xs) = do
a <- x
b <- d xs
return a:b
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
Couldn't match type `a' with [a]
`a' is a rigid type variable bound by
the type signature for d :: [[a]] -> [[a]]
Expected type: [[a]]
Actual type: …Run Code Online (Sandbox Code Playgroud) 我有一些看起来像这样的代码,忽略了与我的问题无关的所有代码:
import qualified Control.Monad.Reader as Reader
data FooEnv = FooEnv { bar :: Int -> Int }
type FooReader = Reader.Reader FooEnv
foo :: Int -> FooReader String
foo i = Reader.liftM show $ bar' i
where
bar' i' = do
bar'' <- Reader.asks bar
return $ bar'' i'
Run Code Online (Sandbox Code Playgroud)
有没有办法重构这个?具体来说,嵌套bar'函数最让我困扰.这可以浓缩成一行吗?
在阅读关于MonadPlus的Haskell Wikibook时,我发现以下函数基本上采用a 和a 并且如果这样的char与字符串头相等则返回:CharStringJust (char,tail)Nothing
char :: Char -> String -> Maybe (Char, String)
char c s = do
let (c':s') = s
if c == c' then Just (c, s') else Nothing
Run Code Online (Sandbox Code Playgroud)
并且他们解释说let (c':s') = s不会产生异常,因为它在一个do块中会评估Nothing模式何时失败,但事实并非如此,因为当我尝试它时:
*Main> char 'a' ""
*** Exception: exercice2.hs:5:7-17: Irrefutable pattern failed for pattern (c' : s')
Run Code Online (Sandbox Code Playgroud)
所以我不得不重写它:
char' :: Char -> String -> Maybe (Char, String)
char' _ [] = …Run Code Online (Sandbox Code Playgroud) 我是Haskell和函数式编程的新手,我想知道为什么这样的例子("嵌套循环")有效:
do
a <- [1, 2, 3]
b <- [4, 5, 6]
return $ a * 10 + b
Run Code Online (Sandbox Code Playgroud)
下面的一些东西是一种伪Haskell语法,但我希望它能说明我的理解.
这是我的理解,它变成了这样的东西
[1, 2, 3] >>= \a ->
([4, 5, 6] >>= \b ->
return $ b * 10 + a)
Run Code Online (Sandbox Code Playgroud)
我想这个表达方式
[4, 5, 6] >>= \b -> return $ b * 10 + a
Run Code Online (Sandbox Code Playgroud)
生成部分应用函数的列表
[[40 + a], [50 + a], [60 + a]]
Run Code Online (Sandbox Code Playgroud)
连接到
[40 + a, 50 + a, 60 + a]
Run Code Online (Sandbox Code Playgroud)
最后一步,看起来像这样
[1, 2, 3] >>= \a …Run Code Online (Sandbox Code Playgroud) 我想写一个简单的游戏“猜数字” -n尝试。我想添加一些条件和命中。是否可以在block内使用守卫do?
这是我的代码:
game = return()
game n = do putStrLn "guess number: 0-99"
number<-getLine
let y = read number
let x =20
| y>x = putStrLn "your number is greater than x"
| y<x = putStrLn "your number is less than x"
| y==x putStrLn "U win!!"
| otherwise = game (n-1)
Run Code Online (Sandbox Code Playgroud)
已经出错
error: parse error on input ‘|’
Run Code Online (Sandbox Code Playgroud)
它可以用一些空白来修复,还是不可能做到?
据我所知,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.
为了生成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) do-notation ×10
haskell ×10
monads ×7
applicative ×1
f# ×1
ghc ×1
guard-clause ×1
reader-monad ×1
refactoring ×1
scala ×1
scope ×1
state-monad ×1
syntax ×1