我想传递一个指向函数的"多态"数组.
我可以在没有警告的情况下做以下事情:
foo (void* ptr);
bar()
{
int* x;
...
foo(x);
}
Run Code Online (Sandbox Code Playgroud)
gcc显然会自动转换x为a (void*),这只是花花公子.
但是,当我执行以下操作时,我会收到警告:
foo (void** ptr);
bar()
{
int** x; // an array of pointers to int arrays
...
foo(x);
}
note: expected ‘void **’ but argument is of type ‘int **’
warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么一个传递(int*)的(void*)参数不是"不兼容",但(int**)作为一个(void**)论据是什么?
由于所有指针类型都是相同的大小(对吗?因为我使用了C已经有一段时间了),我仍然可以做类似的事情:
void mainFunc1(int** arr, int len)
{
//goal is to apply …Run Code Online (Sandbox Code Playgroud) 我正在使用Don Stewart 的软件包System.Random.Mersenne.Pure64和Control.Monad.Mersenne.Random,它们通常非常快,并且应该有助于避免常见错误,例如使用非严格状态monad.
尽管如此,我设法编写了一些代码,这些代码会导致中等大小的向量堆栈溢出.
import qualified Data.Vector.Unboxed as U
import Data.Int
import System.Random.Mersenne.Pure64
import Control.Monad.Mersenne.Random
main = do
let dim = 1000000
y = evalRandom (U.replicateM dim getInt64) (pureMT 13) :: U.Vector Int64
putStr $ (show $ U.head y)
Run Code Online (Sandbox Code Playgroud)
我猜这一定是由于Vector的replicateM实现中的懒惰,虽然它很难看到,因为它是使用实现的streams.
我如何编写使用常量堆栈空间来采样大向量的代码?
我最近发现了Data.Promotion一半的单身人士.它具有大量类型系列,允许在类型级别进行基本上任意计算.我有几个关于用法的问题:
是什么区别($),(%$),($$),和他们在有关:++$,:.$等等?这些实际上是中缀运营商吗?我的印象是所有中缀类型的构造函数都必须以a开头:.
我正在尝试在列表上映射构造函数:
{-# LANGUAGE DataKinds, TypeOperators, PolyKinds #-}
import Data.Promotion.Prelude
data Foo a b
type MyList = '[Int, Double, Float]
-- expects one more argument to `Foo`
type FooList1 b = Map ((Flip Foo) $ b) MyList
-- parse error on the second `b`
type FooList2 b = Map (($ b) :. Foo) MyList
Run Code Online (Sandbox Code Playgroud)
但是我在使用多参数类型构造函数时遇到了麻烦.想法?
我可以用以下函数替换我用等效函数编写的所有类型函数Data.Promotion:
type family ListToConstraint …Run Code Online (Sandbox Code Playgroud)我最近发现-XTypeApplications,它允许我写缩写我的代码.考虑以下:
{-# LANGUAGE AllowAmbiguousTypes, DataKinds, KindSignatures, RankNTypes,
ScopedTypeVariables, TypeApplications #-}
import Data.Tagged
import Data.Proxy
class Foo (a :: Bool) where
foo :: Tagged a Int
instance Foo 'True where
foo = 3
instance Foo 'False where
foo = 4
Run Code Online (Sandbox Code Playgroud)
而不是写作proxy foo (Proxy::Proxy 'True),我现在可以写untag $ foo @'True,这节省了很多Proxy样板.没关系,但我们可以用模糊的类型做得更好:
foo' :: forall (a :: Bool) . (Foo a) => Int
foo' = untag $ foo @a
Run Code Online (Sandbox Code Playgroud)
现在我可以写了foo' @'True!请注意,尽管之前类型不明确-XTypeApplications,但我不再指定类型了a.我认为这很好,但其他人可能不会.所以我希望引入一个包装器 …
我的数据类型总是至少有两个参数,最后两个参数分别是'q'和'm':
{-# LANGUAGE TypeFamilies, FlexibleContexts, UndecidableInstances, TypeOperators, DataKinds, ConstraintKinds, FlexibleInstances #-}
data D1 q m = D1 q
data D2 t q m = D2 q
class Foo a where -- a has kind * -> *
f :: a x -> a x
class (Foo b) => Bar b where -- b has kind * -> *
-- the purpose of g is to change ONE type parameter, while fixing the rest
-- the intent of the equality constraints …Run Code Online (Sandbox Code Playgroud) 我安装了LLVM/opt-3.2以及llvm-3.2.0.2,我刚从Ubuntu软件包安装了GHC 7.6.2.但是,当我尝试使用-fllvm -v3编译ghc时,我收到错误:
*** CodeGen:
*** LlVM CodeGen:
Error (figuring out LLVM version): fd:10: hGetLine: end of file
<no location info>:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM
*** LLVM Optimiser:
'opt-3.0' '/tmp/ghc17812_0/ghc17812_0.ll' '-o' '/tmp/ghc17812_0/ghc17812_0.bc' '-mem2reg' '--enable-tbaa=true'
*** Deleting temp files:
...
ghc: could not execute: opt-3.0
Run Code Online (Sandbox Code Playgroud)
opt在我的路径,但版本是3.2,而不是3.0.如果不是hackage llvm包让GHC寻找合适的opt版本,它是什么?
我想要类似的东西
f :: [forall m. (Mutable v) (PrimState m) r -> m ()] -> v r -> v r -- illegal signature
f gs x = runST $ do
y <- thaw x
foldM_ (\_ g -> g y) undefined gs -- you get the idea
unsafeFreeze y
Run Code Online (Sandbox Code Playgroud)
在Vitus评论的这个问题中,我基本上处于同样的位置:
[I]如果你想在某些结构中保留多态函数,你需要专门的数据类型(例如newtype I = I(forall a.a - > a))或ImpredicativeTypes.
另外,请看这个问题.问题是,这些都是非常难看的解决方案.所以我提出了第三种选择,即通过运行"应该"作为ST计算IO来完全避免多态性.因此f成为:
f :: [(Mutable v) RealWorld r -> IO ()] -> v r …Run Code Online (Sandbox Code Playgroud) 我有一个"线性"类型的家庭,即形式
type family Foo a
type instance Foo T1 = T2
type instance Foo T2 = T3
...
type instance Foo T9 = T10
Run Code Online (Sandbox Code Playgroud)
在我的特定用例中,定义"反向"族FooRev并然后强制执行约束非常方便(FooRev (Foo x) ~ x):
type family FooRev a
type instance FooRev T10 = T9
type instance FooRev T9 = T8
...
type instance FooRev T2 = T1
Run Code Online (Sandbox Code Playgroud)
反向族允许GHC推断许多类型,否则这些类型由于非注入性而会是模糊的.这与此处提出的想法基本相同.这个解决方案非常有效,但是通过列出所有情况,必须定义"反向"类型系列,这很烦人,编程和容易出错.是否有更通用的方法来定义线性族的反转,例如Foo?
考虑以下:
{-# LANGUAGE FlexibleContexts #-}
module Foo where
data D a = D a
class Foo b
instance (Num a) => Foo (D a)
f :: (Foo (D a)) => a -> a
f x = x+1
Run Code Online (Sandbox Code Playgroud)
GHC抱怨它无法推断Num a出来f.我希望从Foofor (非重叠)for的实例推断出这个约束D a.
我知道我可以使用GADT D并在Num a那里添加约束,但我希望不必为了D许多不必要的约束而污染构造函数.这种情况有没有希望发生,现在有可能吗?
我正在使用语法库来处理AST.我有一些奇怪的行为,我不是正在发生的事情.
{-# LANGUAGE TypeOperators, GADTs, FlexibleInstances,
FlexibleContexts, UndecidableInstances #-}
module Foo where
import Data.Syntactic
import Data.Syntactic.Functional
data Const a where Const :: Const (Full a)
instance Render Const where renderSym Const = "const"
main :: ASTF Const Int
main = foo $ inj Const
class Foo dom where
foo :: ASTF dom a -> ASTF dom a
instance --(Const :<: dom) =>
Foo dom where
foo node | Just Const <- prj node = error "PASS"
foo _ …Run Code Online (Sandbox Code Playgroud)