我经常需要序列化/反序列化和类型(例如Either[S,T]
),我还没有找到一种通用或优雅的方法来实现它.这是一个示例类型(基本上相当于Either
)
sealed trait OutcomeType
case class NumericOutcome(units: String) extends OutcomeType
case class QualitativeOutcome(outcomes: List[String]) extends OutcomeType
Run Code Online (Sandbox Code Playgroud)
这是我在实现序列化的伴侣对象上的最大努力.它可以工作,但是为每种总和类型反复编写这些类型的东西是非常烦人的.是否有任何建议使其更好和/或更一般?
import play.api.libs.json._
import play.api.libs.functional.syntax._
object OutcomeType {
val fmtNumeric = Json.format[NumericOutcome]
val fmtQualitative = Json.format[QualitativeOutcome]
implicit object FormatOutcomeType extends Format[OutcomeType] {
def writes(o: OutcomeType) = o match {
case n@NumericOutcome(_) => Json.obj("NumericOutcome" -> Json.toJson(n)(fmtNumeric))
case q@QualitativeOutcome(_) => Json.obj("QualitativeOutcome" -> Json.toJson(q)(fmtQualitative))
}
def reads(json: JsValue) = (
Json.fromJson(json \ "NumericOutcome")(fmtNumeric) orElse
Json.fromJson(json \ "QualitativeOutcome")(fmtQualitative)
)
}
}
Run Code Online (Sandbox Code Playgroud) 我一直在使用Haxl
monad(在这里描述:http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk),它有一个有趣的特性,<*>
因为它的Applicative实例ap
与Control不同.单子.这是一个关键功能,允许它在不阻塞的情况下进行并发计算.例如,如果hf
和ha
是长计算,然后
let hf :: Haxl (a -> b) = ...
ha :: Haxl a = ...
in do
f <- hf
a <- ha
return (f a)
Run Code Online (Sandbox Code Playgroud)
将按顺序执行它们
hf <*> ha
Run Code Online (Sandbox Code Playgroud)
将并行完成它们然后结合结果.
我希望能够运行计算MaybeT Haxl
,但问题是MaybeT m
变换器包中的Applicative实例使用monadic绑定:
instance (Functor m, Monad m) => Applicative (MaybeT m) where
pure = return
(<*>) = ap
Run Code Online (Sandbox Code Playgroud)
ap = liftM2 id
来自哪里Control.Monad
.这使得
let hmf :: MaybeT …
Run Code Online (Sandbox Code Playgroud) 我想定义一个Swappable
具有两个值的特征x,y
和一个swap
方法,以便调用swap
继承自的对象Swappable
返回另一个具有x,y
切换的相同类型的对象.到目前为止,我最好的是:
trait Swappable[T] {
val x: T
val y: T
def swap: Swappable[T] = {
val (a,b) = (x,y)
new Swappable[T] { val x=b; val y=a }
}
}
Run Code Online (Sandbox Code Playgroud)
但这不是我想要的,因为swap的返回类型是一些匿名类,而不是我开始的原始类,所以我得到如下错误:
def direct[S<:Swappable[Int]](s: S): S = if (s.x > s.y) s else s.swap
<console>:32: error: type mismatch;
found : Swappable[Int]
required: S
def direct[S<:Swappable[Int]](s: S): S = if (s.x > s.y) s else s.swap
^
Run Code Online (Sandbox Code Playgroud)
有可能做我想做的事吗?交换的正确类型签名是什么?
我正在尝试以大于双精度的固定精度在Scala(和/或Java)中进行计算.我正在使用带有Scala默认MathContext的 BigDecimals ,它具有精度34.即使所有输入都具有这种精度,我发现经过一些计算后,结果的精度开始爆炸.
这是一个示例计算,我认为说明了问题:
import math.BigDecimal
val z40 = BigDecimal(0).setScale(40) // 0E-40
z40.scale // 40
z40.precision // 1
(1 + z40*z40).precision // 81
Run Code Online (Sandbox Code Playgroud)
结果是81,精度高于z40
.在我的例子中,我从不使用setScale,但是计算中出现了具有非常大比例的零.
这不是我想要的行为.我想要(1 + z40*z40)
精度34 - 正在执行计算的MathContext的精度(因为z40*z40
与1相比可以忽略不计).我怎么能得到这种算术?
更新:此行为是由于Scala 2.9.*和2.10.*之间的MathContexts处理的更改.(感谢Paul Phillips指出了提交.)另见本讨论.
我正在尝试将 Haskell 与具有读取-评估-打印循环的命令行程序连接起来。我想将一些文本放入输入句柄中,然后从输出句柄中读取,直到找到提示(然后重复)。读取应该阻塞,直到找到提示,但不再阻塞。与其编写我自己的小型状态机(一次读取一个字符直到构建提示),不如使用 Parsec 或 Attoparsec 会更好。(一个问题是提示会随着时间的推移而变化,所以我不能只检查恒定的字符串。)
从输出句柄读取适当数量的数据并将其提供给解析器的最佳方法是什么?我很困惑,因为大多数句柄读取原语都要求我事先决定要读取多少数据。但应该由解析器决定何时停止。
我有一个功能
f :: MonadIO m => a -> m b
Run Code Online (Sandbox Code Playgroud)
它接受一些输入并返回将产生输出的IO计算.我想"memoize",f
以便我只为每次输入执行一次这些计算.例如,如果
f :: String -> IO String
f s = putStrLn ("hello " ++ s) >> return s
Run Code Online (Sandbox Code Playgroud)
然后我想要一个memoize
这样的功能
do
mf <- memoize f
s <- mf "world"
t <- mf "world"
return (s,t)
Run Code Online (Sandbox Code Playgroud)
打印"hello world"
一次并返回("world", "world")
.我正在编写的程序是多线程的,所以即使不同的线程都在调用,这个属性也应该保留mf
.
以下是我迄今为止提出的(可怕的)解决方案.我的问题是它是否以及如何改进.
memoize :: (MonadIO m, Ord a) => (a -> m b) -> m (a -> m b)
memoize f = do
cache …
Run Code Online (Sandbox Code Playgroud) 我想为双精度数组定义一些隐式方法,以使我的代码更清晰.理想情况下,它们看起来像这样:
type Vec = Array[Double]
implicit def enrichVec(v: Vec) = new {
def /(x: Double) = v map (_/x)
def *(u: Vec) = (v zip u) map {case (x,y) => x*y} sum
def normalize = v / math.sqrt(v * v)
}
Run Code Online (Sandbox Code Playgroud)
但是,该normalize
函数无法正常工作,因为Scala不会递归地应用隐式方法.具体来说,我收到了一个错误Note: implicit method enrichVec is not applicable here because it comes after the application point and it lacks an explicit result type
.我可以通过明确写出代码来避免这种情况normalize
,但那会很难看.有更好的解决方案吗?
我用Java中的apache.commons.math 将这个样条插值算法转换成Scala,这是我能想到的最简单的方法(见下文).我最终运行的函数运行速度比原始Java代码慢2到3倍.我的猜测是问题源于来自调用的额外循环Array.fill
,但我想不出一个直接的方法来摆脱它们.有关如何使此代码表现更好的任何建议?(以更简洁和/或更实用的方式编写它也会很好 - 在这方面的建议也会受到赞赏.)
type Real = Double
def mySplineInterpolate(x: Array[Real], y: Array[Real]) = {
if (x.length != y.length)
throw new DimensionMismatchException(x.length, y.length)
if (x.length < 3)
throw new NumberIsTooSmallException(x.length, 3, true)
// Number of intervals. The number of data points is n + 1.
val n = x.length - 1
// Differences between knot points
val h = Array.tabulate(n)(i => x(i+1) - x(i))
var mu: Array[Real] = Array.fill(n)(0)
var z: Array[Real] = Array.fill(n+1)(0)
var i …
Run Code Online (Sandbox Code Playgroud) 我在emacs中编辑Mathematica代码.Mathematica的希腊字母的明文表示看起来像
\[Alpha], \[Beta], \[Gamma], ...
Run Code Online (Sandbox Code Playgroud)
我不介意输入这些,但结果代码很大,看起来很笨重,例如:
k[\[Beta]_,z_]:=z^(\[Beta]/2) Hypergeometric2F1[\[Beta]/2,\[Beta]/2,\[Beta],z];
Run Code Online (Sandbox Code Playgroud)
有没有办法使emacs自动显示某些字符串(如\[Alpha]
)作为其他字符串(如alpha的unicode字符)?注意,我不想实际用另一个字符串替换一个字符串(如果我理解的话,这是缩写的缩写),因为Mathematica仍然可以正确读取该文件.
scala ×5
haskell ×3
java ×2
applicative ×1
attoparsec ×1
bigdecimal ×1
concurrency ×1
emacs ×1
haxl ×1
implicit ×1
inheritance ×1
json ×1
math ×1
memoization ×1
monads ×1
parsec ×1
parsing ×1
performance ×1
spline ×1
traits ×1