我一直在玩Simon Marlow关于Haskell中的并行和并发编程的书中的一些例子,偶然发现了一个我不太了解的有趣行为.这真的是我试图了解GHC的一些内部运作方式.
假设我在REPL中执行以下操作:
?» let x = 1 + 2 :: Int
?» let z = (x,x)
?» :sprint x
x = _
?» :sprint z
z = (_,_)
?» seq x ()
()
?» :sprint z
z = (3,3)
Run Code Online (Sandbox Code Playgroud)
好吧,这几乎是我的预期,除了z已经被评估为WHNF.让我们编写一个类似的程序并将其放在一个文件中:
module Thunk where
import Debug.Trace
x :: Int
x = trace "add" $ 1 + 2
z :: (Int,Int)
z = (x,x)
Run Code Online (Sandbox Code Playgroud)
在GHCi中摆弄它:
?» :sprint x
x = _
?» :sprint z
z = _
?» seq x () …
Run Code Online (Sandbox Code Playgroud) 我在一个拥有12个内核的系统上运行了几个Haskell进程.所有进程都-threaded
使用12种功能进行编译和运行.他们都使用的一个库resource-pool
保存了一个数据库连接池.
有趣的是,即使所有进程实际上都处于空闲状态,它们也会占用大约2%的CPU时间.检查这些进程之一strace -p $(pgrep processname) -f
表明该进程正在进行不合理的系统调用,即使它实际上不应该做任何事情.把事情放到透视中:
-N2
5秒会生成66K日志文件.-N64
产生60 兆字节的日志.因此,功能的数量会增加大量发布的系统调用量.
深入挖掘,我们发现resource-pool
正在运行一个收割机线程,它会每秒触发一次,以检查它是否可以清理一些资源.我们可以用这个简单的程序模拟相同的行为.
module Main where
import Control.Concurrent
import Control.Monad (forever)
main :: IO ()
main = forever $ do
threadDelay (10 ^ 6)
Run Code Online (Sandbox Code Playgroud)
如果我传递-B
给运行时系统,每当发出GC时我都会得到音频反馈,在这种情况下每隔60秒就会发出一次.
因此,当我通过传递-I0
给RTS来抑制这些GC周期时,strace
在该进程上运行命令只会产生大约70K的大型日志文件.由于该进程也在运行scotty
服务器,因此在请求进入时会触发GC,因此它们似乎在我真正需要它时发生.
由于我们将在明年的过程中大量增加这台机器上的Haskell进程数量,我想知道如何将它们的空闲时间保持在合理的水平.显然,过往-I0
似乎是一个相当糟糕的主意(?).另一个想法是将功能的数量从12减少到类似4的东西.有没有其他方法来调整RTS以便我可以在空闲时保持进程从刻录到多个CPU周期?
当使用模式匹配模式匹配并打开所有警告时,我正在观察一个有趣的行为
{-# OPTIONS_GHC -Wall #-}
module Mood where
data Mood = Happy
| Indifferent
| Sad
deriving Show
flipMood :: Mood -> Mood
flipMood Happy = Sad
flipMood Indifferent = Indifferent
flipMood Sad = Happy
flipMood' :: Mood -> Mood
flipMood' mood
| Happy <- mood = Sad
| Indifferent <- mood = Indifferent
| Sad <- mood = Happy
Run Code Online (Sandbox Code Playgroud)
即使flipMood
并且flipMood'
几乎做同样的事情我得到以下错误消息:
Mood.hs:15:1: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘flipMood'’: Patterns not matched: _ …
Run Code Online (Sandbox Code Playgroud) 我一直在尝试与Codensity
最近这应该涉及DList
与[]
除其他事项外.无论如何,我从来没有找到说明这种关系的代码.经过一些实验,我最终得到了这个:
{-# LANGUAGE RankNTypes #-}
module Codensity where
newtype Codensity f a = Codensity
{ runCodensity :: forall b. (a -> f b) -> f b }
type DList a = Codensity [] [a]
nil :: DList a
nil = Codensity ($ [])
infixr 5 `cons`
cons :: a -> DList a -> DList a
cons x (Codensity xs) = Codensity ($ (xs (x:)))
append :: DList a -> DList a -> DList a …
Run Code Online (Sandbox Code Playgroud) 我有一个理论问题,关于一个类型的性质,在很多例子中用于解释Coyoneda引理.它们通常被称为"自然变换",据我所知,它们是仿函数之间的映射.令我困惑的是,在这些例子中,他们有时会映射Set
到一些仿函数F
.所以它并不是真正意义上的仿函数之间的映射,而是一些更轻松的东西.
这是有问题的代码:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
module Coyo where
import Data.Set (Set)
import qualified Data.Set as Set
data Coyoneda f a where
Coyoneda :: (b -> a) -> f b -> Coyoneda f a
instance Functor (Coyoneda f) where
fmap f (Coyoneda c fa) = Coyoneda (f . c) fa
set :: Set Int
set = Set.fromList [1,2,3,4]
lift :: f a -> Coyoneda f a
lift fa = Coyoneda id fa …
Run Code Online (Sandbox Code Playgroud) 所以,我正在DataKinds
和TypeFamilies
Haskell 一起玩,并开始关注生成的Core GHC.
这是一个小TestCase来激发我的问题:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
module TestCase where
data Ty = TyBool | TyInt
type family InterpTy (t :: Ty) :: *
type instance InterpTy TyBool = Bool
type instance InterpTy TyInt = Int
data Expr (a :: Ty) where
I :: Int -> Expr TyInt
B :: Bool -> Expr TyBool
eval :: Expr a -> InterpTy a
eval (I …
Run Code Online (Sandbox Code Playgroud) 现在我知道这个问题实际上并不是一个非常技术性的问题,而是一段困扰我一段时间的问题.实际上我们在公司使用了很多C++和PHP,我们的一些开发人员真的希望有一种新的现代语言可以帮助我们提高效率.我一直在谈论scala可以做什么,而其他程序员似乎对该语言产生了一些兴趣.艰难的工作是,你如何说服你的老板将scala视为公司的语言.我看到了"将Scala偷偷带入您的公司"的演示文稿,但它处理的是您在公司使用Java而我们没有使用Java的情况.
你如何对抗通常的"那只是深奥的东西"和"我们已经可以在$ LANGUAGE中做到这一点"的论点.我正在计划谈论Scala,因为我没有太多时间,我需要想法如何让人们对语言感兴趣,而不是设置像"currying"这样的反应?我们已经可以通过boost ::绑定".
你们是怎么做到的?
问候,raichoo
编辑:昨天发表讲话,人们非常兴奋.我的公司将试一试!谢谢你的所有建议.
我最近一直在玩提取器,并且想知道List提取器如何工作尤其如此:
List(1, 2, 3) match {
case x :: y :: z :: Nil => x + y + z // case ::(x, ::(y, ::(z , Nil)))
}
Run Code Online (Sandbox Code Playgroud)
Ok ::用在模式中,所以我猜编译器现在在:: - Object中查找unapply方法.试过这个:
scala> (::).unapply(::(1, ::(2, Nil)))
res3: Option[(Int, List[Int])] = Some((1,List(2)))
Run Code Online (Sandbox Code Playgroud)
很好,有效.但是,这不是:
scala> (::).unapply(List(1,2,3))
<console>:6: error: type mismatch;
found : List[Int]
required: scala.collection.immutable.::[?]
(::).unapply(List(1,2,3))
Run Code Online (Sandbox Code Playgroud)
这样做:
scala> List.unapplySeq(List(1,2,3))
res5: Some[List[Int]] = Some(List(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
其实我此刻有点困惑.编译器如何在此处选择正确的unapply实现.
我最近一直在玩Scala并且正在考虑如何在其中实现一个通用版本的quicksort(只是为了更好地感受语言)
我想出了类似的东西
object Main {
def qs[T](a: List[T], f: (T, T) => Boolean): List[T] = {
if (a == Nil) return a
val (l, g) = a drop 1 partition (f(a(0),(_:T)))
qs(l, f) ::: List(a(0)) ::: qs(g, f)
}
def main(args: Array[String]): Unit = {
val a = List(5,3,2,1,7,8,9,4,6)
val qsInt = qs(_: List[Int], (_: Int) > (_: Int))
println(qsInt(a))
}
}
Run Code Online (Sandbox Code Playgroud)
这不像我想要的那样通用,因为我必须明确说明如何对元素进行排序而不是仅仅做类似的事情
val (l, g) = a drop 1 partition (a(0) >)
Run Code Online (Sandbox Code Playgroud)
如何告诉编译器T只需要实现大于运算符,可以通过这个函数进行排序?
问候
我试图通过实现一个描述monad的非常基本的接口来掌握scala中的高阶多态性,但我遇到了一个我不太了解的问题.
我用C++实现了相同的代码,代码如下所示:
#include <iostream>
template <typename T>
class Value {
private:
T value;
public:
Value(const T& t) {
this->value = t;
}
T get() {
return this->value;
}
};
template < template <typename> class Container >
class Monad {
public:
template <typename A> Container<A> pure(const A& a);
};
template <template <typename> class Container>
template <typename A>
Container<A> Monad<Container>::pure(const A& a) {
return Container<A>(a);
}
int main() {
Monad<Value> m;
std::cout << m.pure(1).get() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当尝试使用scala执行相同操作时,我失败了:
class Value[T](val …
Run Code Online (Sandbox Code Playgroud) haskell ×6
scala ×4
ghc ×2
list ×2
algorithm ×1
casting ×1
concurrency ×1
data-kinds ×1
extractor ×1
ghci ×1
monads ×1
polymorphism ×1
thunk ×1
types ×1