这是一个与用于为Haskell库定义自己的Monad实例的API设计实践相关的问题.定义Monad实例似乎是隔离DSL的好方法,例如Parmonad-par中的monad,hdph; Process在分布式过程中; Eval并行等...
我拿两个haskell库的例子,其目的是使用数据库后端的IO.我采取的例子了Riak对了Riak IO和HEDIS对Redis的IO.
在hedis中,定义了Redismonad .从那里,您使用redis运行IO:
data Redis a -- instance Monad Redis
runRedis :: Connection -> Redis a -> IO a
class Monad m => MonadRedis m
class MonadRedis m => RedisCtx m f | m -> f
set :: RedisCtx m f => ByteString -> ByteString -> m (f Status)
example = do
conn <- connect defaultConnectInfo
runRedis conn $ do
set "hello" "world"
world …Run Code Online (Sandbox Code Playgroud) Haskell repa库用于在CPU上自动并行计算数组.加速库是GPU上的自动数据并行.API非常相似,具有相同的N维数组表示.人们甚至可以切换与加速,维修服务阵列fromRepa和toRepa在Data.Array.Accelerate.IO:
fromRepa :: (Shapes sh sh', Elt e) => Array A sh e -> Array sh' e
toRepa :: Shapes sh sh' => Array sh' e -> Array A sh e
Run Code Online (Sandbox Code Playgroud)
有多个后端用于加速,包括LLVM,CUDA和FPGA(参见http://www.cse.unsw.edu.au/~keller/Papers/acc-cuda.pdf的图2 ).虽然图书馆似乎没有得到维护,但我发现了一个加速的后端.鉴于修复和加速编程模型是相似的,我希望在它们之间有一种优雅的切换方式,即一次写入的函数可以用repa的R.computeP执行,或者用加速的后端执行,例如使用CUDA 运行函数.
采用简单的图像处理阈值功能.如果灰度像素值小于50,则将其设置为0,否则保留其值.这是它对南瓜的作用:
以下代码介绍了修复和加速实现:
module Main where
import qualified Data.Array.Repa as R
import qualified Data.Array.Repa.IO.BMP as R
import qualified Data.Array.Accelerate as A
import qualified Data.Array.Accelerate.IO as A
import qualified Data.Array.Accelerate.Interpreter as A
import Data.Word …Run Code Online (Sandbox Code Playgroud) 列表理解很容易理解.请看h以下定义.它使用pure_xs类型[Int]和pure_f类型Int -> String,在列表推导中使用两者.
pure_xs :: [Int]
pure_xs = [1,2,3]
pure_f :: Int -> String
pure_f a = show a
h :: [(Int,Char)]
h = [(a,b) | a <- pure_xs, b <- pure_f a]
-- h => [(4,'4'),(5,'5'),(6,'6')]
Run Code Online (Sandbox Code Playgroud)
大.现在采取两个略有不同的表达,monadic_f并且monadic_xs.我想g使用列表推导构建,看起来尽可能相似h.我有一种感觉,解决方案将涉及生成一系列IO操作,并使用sequence生成[(Int,Char)]IO monad 中的类型列表.
monadic_xs :: IO [Int]
monadic_xs = return [1,2,3]
monadic_f :: Int -> IO String
monadic_f a = return …Run Code Online (Sandbox Code Playgroud) 我想使用Haskell的parsec库实现这个语法规则:
((a | b | c)* (a | b))?
Run Code Online (Sandbox Code Playgroud)
哪个是接受可选(即可能为空)字符串的解析器规则.如果它所接受的字符串不为空,则可以通过传递零次或多次出现的a b或者c解析器来使用它,但是最外部?可选解析器所接受的字符串必须由解析器消耗,a或者b不是c.这是一个例子:
module Main where
import Text.Parsec
import Text.Parsec.Text
a,b,c :: GenParser () Char
a = char 'a'
b = char 'b'
c = char 'c'
-- ((a | b | c)* (a | b))?
myParser = undefined
shouldParse1,shouldParse2,shouldParse3,
shouldParse4,shouldFail :: Either ParseError String
-- these should succeed
shouldParse1 = runParser myParser () "" "" -- because …Run Code Online (Sandbox Code Playgroud) 我有一个我想hist在 R 中绘制的数据集。数据集中有许多行的值超出了我关心的值。具体来说,我的 R 脚本是:
library(ggplot2)
data = read.table("input.txt", sep=" ", strip.white=TRUE, header=TRUE)
pdf("out.pdf")
hist(data$actions,breaks=seq(0,130,by=1))
dev.off()
Run Code Online (Sandbox Code Playgroud)
一个示例数据集input.txt是:
name actions
foo 3
bar 129
baz 131
Run Code Online (Sandbox Code Playgroud)
如果我运行 R 脚本,我会收到一个错误:
hist.default(data$actions,breaks = seq(0, 130, by = 1), 中的错误:
一些 'x' 未计算在内;也许 'breaks' 不跨越 'x'
调用的范围:hist -> hist。默认
执行停止
我知道为什么会出现这个错误:出现了一次大于 130baz的值,即值为 131。
我想要的是仅为0 到 130 指定范围内的频率创建直方图,并且对于该范围之外的所有频率都将被静默忽略。我怎样才能做到这一点?
我正在通过尝试大量的编程示例来探索Haskell修复库.我的目标是使用repa实现常见的图像处理算法.
在repa存储库中有一些有用的代码示例.它们都在类型Array U DIM2 a或Array DIM2 Float或的图像上运行Array U DIM2 Double.
-- three image types used below
type Image = Array U DIM2 Double
type Image = Array DIM2 Float
type Image = Array U DIM2 (Word8, Word8, Word8)
-- examples/Blur/src-repa/Main.hs
blur :: Monad m => Int -> Array U DIM2 Double -> m (Array U DIM2 Double)
-- examples/Laplace/src-repa/SolverStencil.hs
solveLaplace :: Monad m => Int -> Array U DIM2 …Run Code Online (Sandbox Code Playgroud) 省略函数参数是简洁的Haskell代码的一个很好的工具.
h :: String -> Int
h = (4 +) . length
Run Code Online (Sandbox Code Playgroud)
如何在case语句中省略数据构造函数参数.下面的代码可能被认为有点蹩脚,其中s和i是最后的参数A,B但是作为每个案例匹配的主体中的最终参数重复.
f :: Foo -> Int
f = \case
A s -> 4 + length s
B i -> 2 + id i
Run Code Online (Sandbox Code Playgroud)
有没有办法在案例模式匹配中省略这些参数?对于具有大量参数的构造函数,这将从根本上缩短代码宽度.例如以下伪代码.
g :: Foo -> Int
g = \case
{- match `A` constructor -> function application to A's arguments -}
A -> (4 +) . length
{- match `B` constructor -> function application to B's arguments -} …Run Code Online (Sandbox Code Playgroud) 小写的unicode s是U + 0073,该网站称其为\u0073C和Java.
给定一个文件:a.txt包含:
http://www.example.com/\u0073
Run Code Online (Sandbox Code Playgroud)
让我们用Java阅读这篇文章,\然后看看我们得到了什么:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.apache.commons.lang3.StringEscapeUtils;
public class Main {
public static void main(String[] args) throws IOException {
String s2 = new String(Files.readAllBytes(Paths.get("a.txt")));
System.out.println(s2); // prints http://www.example.com/\u0073
String s3 = org.apache.commons.lang3.StringEscapeUtils.unescapeJava(s2);
System.out.println(s3); // prints http://www.example.com/s
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
$ java -cp ./commons-lang3-3.4.jar:. Main
http://www.example.com/\u0073
http://www.example.com/s
Run Code Online (Sandbox Code Playgroud)
所述unescapeJava(s2)方法调用取\\u0073从文件和取消转义到\u0073,然后印刷变为"S".
我们可以在Haskell中做同样的事吗?
让我们使用文本库来使用这两个文件:
Prelude > a <- Data.Text.IO.readFile "a.txt"
Prelude > …Run Code Online (Sandbox Code Playgroud) 这里的两位非常简单的功能f和g.
{-# LANGUAGE ScopedTypeVariables #-}
module Test where
import Control.Applicative
f :: IO ()
f = do
y <- (<*>) (pure (show . (*10))) (read <$> readFile "data")
writeFile "out" y
g :: IO ()
g = do
y <- (readFile "data" >>= return . show . (*10) . read)
writeFile "out" y
Run Code Online (Sandbox Code Playgroud)
读取文件并*10在f写入应用性风格pure和(<*>).读取和*10输入的文件g是以monadic样式编写的>>=.(我一直在使用刻意避免liftM在g强调以下问题).
f和之间的语义差异是g什么?或者在这种情况下,它只是一种风格选择吗?