我刚刚了解了GHC的StablePointer功能,这很酷,但我无法弄清楚为什么它不会显示相同的东西.这是我的测试用例:
-- Example 1
import System.Mem.StableName
data Wrapper = Wrapper { getWrapper :: Int -> Bool }
myFunc :: Int -> Bool
myFunc = (> 4)
main :: IO ()
main = do
let m = Wrapper myFunc
a <- makeStableName $ getWrapper m
b <- makeStableName $ getWrapper m
print (a `eqStableName` b)
putStrLn "Done"
Run Code Online (Sandbox Code Playgroud)
非常简单,但是当我runhaskell使用GHC 7.8.4时,我得到了错误的结果.一个更简单的案例怎么样?我们试试这个:
-- Example 2
import System.Mem.StableName
main :: IO ()
main = do
let m = (+2) :: Int …Run Code Online (Sandbox Code Playgroud) 在乙烯基库中,有一个RecAll类型族,让我们要求对类型级别列表中的每个类型使用部分应用的约束.例如,我们可以这样写:
myShowFunc :: RecAll f rs Show => Rec f rs -> String
Run Code Online (Sandbox Code Playgroud)
这一切都很可爱.现在,如果我们的约束RecAll f rs c在哪里c是未知的,并且我们知道c x需要d x(借用ekmett的contstraints包中的语言),我们怎么能得到RecAll f rs d?
我问的原因是我正在处理一些需要满足几个类型类约束的函数中的记录.要,我现在用的是做这个:&:组合子从Control.Constraints.Combine模块中存在的包.(注意:如果安装了其他东西,则不会构建软件包,因为它依赖于超级旧版本contravariant.您可以复制我提到的一个模块.)有了这个,我可以得到一些非常漂亮的约束,同时最小化类型类肉鸡.例如:
RecAll f rs (TypeableKey :&: FromJSON :&: TypeableVal) => Rec f rs -> Value
Run Code Online (Sandbox Code Playgroud)
但是,在这个函数的主体内部,我调用另一个需要较弱约束的函数.它可能看起来像这样:
RecAll f rs (TypeableKey :&: TypeableVal) => Rec f rs -> Value
Run Code Online (Sandbox Code Playgroud)
GHC无法看到第二个声明来自第一个声明.我认为情况就是这样.我看不到的是如何证明它以实现它并帮助GHC.到目前为止,我有这个:
import Data.Constraint
weakenAnd1 :: ((a …Run Code Online (Sandbox Code Playgroud) GHC在将它们传递给函数时是否会解压缩类型?例如,假设我们有以下类型:
data Foo
= Foo1 {-# UNPACK #-} !Int {-# UNPACK #-} !Word
| Foo2 {-# UNPACK #-} !Int
| Foo3 {-# UNPACK #-} !Word
Run Code Online (Sandbox Code Playgroud)
然后我在其Foo参数中定义一个严格的函数:
consumeFoo :: Foo -> Int
consumeFoo x = case x of ...
Run Code Online (Sandbox Code Playgroud)
在运行时,当我打电话时,我consumeFoo可以期待发生什么?该GHC调用约定是通过参数寄存器(或在栈上一次有太多).我可以看到论证传递的两种方式:
Foo堆上的指针作为一个参数传入.Foo,一个参数表示使用的数据构造函数,另外两个表示数据构造函数中的可能Int和Word值.我更喜欢第二种表示,但我不知道它是否真的发生了什么.我知道UnpackedSumTypes登陆GHC 8.2,但目前还不清楚它是否符合我的要求.如果我把函数写成:
consumeFooAlt :: (# (# Int#, Word# #) | Int# | Word# #) -> Int
Run Code Online (Sandbox Code Playgroud)
那么我希望评估(2)会发生什么.而且开箱部分解压后的款项页面的指示,我能做到这一点,以及:
data Wrap = Wrap …Run Code Online (Sandbox Code Playgroud) 我正在努力更好地理解网络库中的设计决策.信誉良好的来源在github问题和使用非阻塞套接字的邮件列表响应中提及network.他们使用select来阻止,直到套接字准备好被读取,而不是使用默认的阻塞行为.为什么这样更好?无论哪种方式,它最终都会阻塞,并且network只向最终用户公开阻止API.我的猜测是,阻止FFI调用是不好的,并且存在某种GHC魔法select,但我无法证实这一点.
作为未成年人之外,我找不到地方select在叫network.打顶代码库没有出现任何问题.我刚刚发现了GHC.Event,它似乎提供了可以用来代替select直接调用的函数,但是grepping shownetwork也没有使用它.
该模块GHC.TypeLits目前提供natVal和symbolVal,这使我们能够获得从类型的一种运行时值Nat或Symbol.有没有办法让类型的运行时值[String]出型样的'[Symbol]?我看不出一个明显的方法来做到这一点.我可以想到一个使用类型类的东西OverlappingInstances,但似乎GHC应该已经有了这个功能.
我有一个简单的例程,它采用了向量的乘积Double.我试图并行化这个代码,但许多火花最终失败了.这是一个独立的基准,也作为要点提供:
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# OPTIONS_GHC -O2 -Wall -threaded -fforce-recomp #-}
import Criterion.Main
import Control.Monad (when)
import Control.Parallel.Strategies (runEval,rpar,rseq)
import qualified Data.Vector.Primitive as PV
main :: IO ()
main = do
let expected = PV.product numbers
when (not (serialProduct numbers == expected)) $ do
fail "serialProduct implementation incorrect"
defaultMain
[ bgroup "product"
[ bench "serial" $ whnf serialProduct numbers
, bench "parallel" $ whnf parallelProduct numbers
]
]
numbers :: PV.Vector …Run Code Online (Sandbox Code Playgroud) 我花了一些时间试图理解模板haskell生成的代码,在这个例子中取自Yesod书:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Person
name String
age Int
deriving Show
Car
color String
make String
model String
deriving Show
|]
Run Code Online (Sandbox Code Playgroud)
我觉得我经常看到发生了什么(很多类型编组),但有一节仍然让我感到困惑:
instance PersistEntity (PersonGeneric backend) where
data instance Unique (PersonGeneric backend) =
data instance EntityField (PersonGeneric backend) typ
= typ ~ KeyBackend backend (PersonGeneric backend) => PersonId |
typ ~ String => PersonName |
typ ~ Int => PersonAge
type instance PersistEntityBackend (PersonGeneric backend) =
backend
Run Code Online (Sandbox Code Playgroud)
数据实例instance EntityField (PersonGeneric backend) typ有三个数据构造函数,这是有意义的(数据库中的每一列都有一个),但即使在查找了代号在haskell中的作用之后,我也无法理解它在那里做了什么.=>通常用于通用量化的原因通常用于似乎没有任何类型的东西?
如果我能以某种方式更清楚,请告诉我.
在GHCJS下,如何getCurrentTime运作?在time库本身中,这是使用FFI实现的,调用操作系统提供的功能.但是,time开头没有任何行:
foreign import javascript ...
Run Code Online (Sandbox Code Playgroud)
我检查了shimsGHCJS用来修补库的存储库.它修补了时区获取功能,但没有提及getCurrentTime.我发现的唯一远程关闭的东西是在ghcjs-boot哪里old-time修补:
#ifdef ghcjs_HOST_OS
type CTimeVal = ()
type CTimeZone = ()
...
foreign import ccall unsafe "HsTime.h __hscore_gettimeofday"
gettimeofday :: Ptr CTimeVal -> Ptr CTimeZone -> IO CInt
...
Run Code Online (Sandbox Code Playgroud)
但是这有两个问题.一个是它不是正确的库(old-time而不是time).另一个是它仍在使用C FFI.我不明白在使用GHCJS进行编译时如何使用C FFI.
那么,哪里getCurrentTime可以为GHCJS填充?
在回复关于grepping ghcjs源的评论时,如果我getTime在GHCJS的源代码中搜索(我相信这将是使用的javascript函数),我基本上什么也得不到.但是,通过all.jsgreping GHCJS为使用的项目生成的文件getCurrentTime,我得到:
ag '\bgetTime\b' all.js
20948: h$log((("elapsed time: " + (h$RTS_597.getTime() …Run Code Online (Sandbox Code Playgroud) 对于我所知道的所有 C 编译器,-Wall都会对隐式转换发出警告,但不会对任何显式转换发出警告。我一直在尝试找到一个标志(无论是 gcc、clang、任何 c 编译器都可以),当存在导致未定义或实现定义的行为的强制转换时,该标志将导致发出警告。这是一个示例,说明了我期望和不期望出现警告的位置:
#include <math.h>
struct person {
int tag;
char* name;
};
int foo(struct person* p) {
int* tagPtr = (int*)p; // this cast is fine, cast to first member ptr is allowed
double* badPtr = (double*)p; // this cast should cause warning
return ((*tagPtr) + (int)(round(*badPtr)));
}
Run Code Online (Sandbox Code Playgroud)
到 a 的转换int*是明确定义的,并且到double*没有明确定义,但 gcc 不会警告我有关第二次强制转换的信息。有没有办法让它这样做?或者其他编译器甚至 linter 是否提供此功能?
然后是“明确定义的”和“明确定义的实现”之间的区域,即“可以根据上下文进行明确的定义”。例如,如果 a最初是通过另一个方向的转换形成的(由 C 规范的 6.7.2.1p15 节暗示),则从aint*到 a 的转换struct person*是明确定义的。int*指针的出处很少可用,因此编译器或 …
haskell ×9
ghc ×7
c ×1
clang ×1
constraints ×1
gcc ×1
gcc-warning ×1
ghcjs ×1
persistent ×1
vector ×1
vinyl ×1
yesod ×1