我使用列表推导编写了一个递归算法来执行递归.我认为我的代码清晰易读,其产生的结果是正确的.
但是,我发现很难理解我的代码在某些输入上的性能.我认为使用Writer monad将一些日志记录放入我的代码中会很有用.
我发现将非monadic代码转换为monadic非常困难.最终我得到它编译并正确运行,但monadic代码比原始代码更难理解.
原始问题太复杂了,无法在这里解释,所以我写了一个玩具示例,显示非monadic和monadic方法,但实际上并没有计算任何有用的东西!
所以我的问题是:有没有更好的方法来编写函数fMonadic,这样它更具可读性?
import Control.Monad (forM)
import Control.Monad.Writer (Writer, runWriter, tell)
fun :: Int -> [[Int]] -> [[Int]]
fun a b = map (map (a +)) b
fNonMonadic :: [[Int]] -> [[Int]]
fNonMonadic [] = [[]]
fNonMonadic (first : rest) =
[ first ++ s
| e <- first
, s <- fNonMonadic $ fun e rest]
fMonadic :: [[Int]] -> Writer [String] [[Int]]
fMonadic [] = do
tell ["base case"]
return [[]]
fMonadic (first : rest) …Run Code Online (Sandbox Code Playgroud) 这是关于如何在Haskell中执行某些操作的问题,这在Python3中很容易实现.
我有一个使用生成器的Python3程序,如下所示:
def gen(filename):
for line in open(filename):
line = line.rstrip()
print(f"From {filename} about to yield the line {line}")
yield line
print(f"From {filename} recently yielded the line {line}")
if "." in line:
yield from gen(line)
for line in gen("a.txt"):
print(f"Main program has {line}")
Run Code Online (Sandbox Code Playgroud)
如果我给它一个输入文件a.txt包含以下内容:
First line of a
b.txt
Third line of a
Run Code Online (Sandbox Code Playgroud)
和另一个包含以下内容的输入文件b.txt:
First line of b
Second line of b
Run Code Online (Sandbox Code Playgroud)
那么输出,正如我所料,是:
From a.txt about to yield the line First line of a
Main program has First line of …Run Code Online (Sandbox Code Playgroud) 考虑以下(非常沉闷)游戏: - 玩家A认为1到100之间的数字. - 玩家B允许5次尝试猜测该数字.玩家A将对每个猜测做出"太大","太小"或"正确"的回应.
我想在Haskell中模拟这个,当然这很简单.但是为了让事情变得有趣,我想以玩家B不能"欺骗"的方式编写代码.这意味着两件事: - 玩家B代码不允许查看密码的正确值.播放器A代码为播放器B代码提供了一个函数,用于检查其猜测. - 不允许玩家B代码调用该函数超过五次.不知何故,播放器A代码必须保持调用函数的次数.
这在使用私有可变变量的OO语言中很容易实现.
在Haskell中,我使用IORef对其进行编码以记录调用次数.那很好,我认为我的解决方案是正确的.但我的问题是:
"如果没有IORef或者类似的话,这可以在Haskell中完成吗?是否有一个我错过的纯功能解决方案?"
这是我的Haskell代码:
import Data.IORef (newIORef, readIORef, writeIORef)
import System.Random (randomRIO)
lowest = 1
highest = 100
maxtries = 5
playerA :: IO (Int -> IO (Maybe Ordering))
playerA = do
secret <- randomRIO (lowest, highest)
print ("Secret", secret)
tries <- newIORef maxtries
return $ \ guess -> do
t <- readIORef tries
if t == 0 then
return Nothing
else do
writeIORef tries $ t - 1
return …Run Code Online (Sandbox Code Playgroud)