写完这篇文章之后,我决定将我的钱放在我的嘴边,并开始转换我以前使用的项目recursion-schemes.
有问题的数据结构是一个懒惰的kdtree.请查看具有显式和隐式递归的实现.
这主要是一种简单的转换:
data KDTree v a = Node a (Node v a) (Node v a) | Leaf v a
Run Code Online (Sandbox Code Playgroud)
至
data KDTreeF v a f = NodeF a f f | Leaf v a
Run Code Online (Sandbox Code Playgroud)
现在对整个shebang进行基准测试后,我发现该KDTreeF版本比普通版本慢了两倍(在这里找到整个版本).
这只是额外的Fix包装,让我放慢了速度吗?有什么我可以做的吗?
cata (fmap foo algebra)了好几次.这是好习惯吗?recursion-schemes包.这有关系吗?https://ghc.haskell.org/trac/ghc/wiki/NewtypeWrappers
是newtype Fix f = Fix …
我所说的是无法定义:
data A = A {name :: String}
data B = B {name :: String}
Run Code Online (Sandbox Code Playgroud)
我知道GHC只是将其解释为普通函数,解决这个问题的惯用方法是:
data A = A {aName :: String}
data B = B {bName :: String}
class Name a where
name :: a -> String
instance Name A where
name = aName
instance Name B where
name = bName
Run Code Online (Sandbox Code Playgroud)
写完这篇文章之后,我不太喜欢它......难道这个类型化不能成为荒谬过程的一部分吗?
当我写一些Aeson JSON解析时,我想到了这个想法.如果只是为每种数据类型派生FromJSON实例都太容易了,我必须手工编写所有内容(目前> 1k行和计数).拥有像name或简单地value在数据记录中的名称并不常见.
http://www.haskell.org/haskellwiki/Performance/Overloading提到函数重载会引入一些运行时开销.但实际上我不明白为什么编译器无法在编译时解析它并在内部给它们不同的名称.
这个来自2012年的SO问题或多或少地说明了历史原因并指出了2006年的邮件主题.最近有什么变化吗?
即使存在一些运行时开销,大多数人也不会介意,因为大多数代码几乎不是性能关键.
是否有一些隐藏的语言扩展实际允许这个?我不确定......但我认为伊德里斯实际上是这样做的?
给定一个免费的monad DSL,例如:
data FooF x = Foo String x
| Bar Int x
deriving (Functor)
type Foo = Free FooF
Run Code Online (Sandbox Code Playgroud)
并随机翻译Foo:
printFoo :: Foo -> IO ()
printFoo (Free (Foo s n)) = print s >> printFoo n
printFoo (Free (Bar i n)) = print i >> printFoo n
Run Code Online (Sandbox Code Playgroud)
在我看来,应该可以在printFoo的每个迭代中散布一些东西,而无需手动操作:
printFoo' :: Foo -> IO ()
printFoo' (Free (Foo s n)) = print s >> print "extra info" >> printFoo' n
printFoo' (Free (Bar i n)) = print …Run Code Online (Sandbox Code Playgroud) 鉴于:
newtype MyVec = MyVec { unVec :: Data.Vector }
deriving (Functor, etc)
Run Code Online (Sandbox Code Playgroud)
这将创建(类似)这个:
instance Functor MyVec where
fmap f = MyVec . Data.Vector.fmap f . unVec
Run Code Online (Sandbox Code Playgroud)
Vector Vectors融合规则会被激活并重fmap f . fmap g $ myVec写成fmap (f . g) myVec?
我应该注意哪些陷阱?在GHC 7.8中解决了为容器中的新类型"支付"的问题,是吗?
在我看来,这两个想法之间存在着密切的联系.我的猜测是,如果有一种方法可以用迭代器表示任意图形,那么FRP可以用Iteratees来实现.但是afaik他们只支持链式结构.
有人可以对此有所了解吗?
我目前正在寻找一种优雅且高效的解决方案来解决我认为很常见的问题.考虑以下情况:
我定义了一个基于BTree的文件格式(以简化的方式定义),如下所示:
data FileTree = FileNode [Key] [FileOffset]
| FileLeaf [Key] [Data]
Run Code Online (Sandbox Code Playgroud)
从文件读取和写入到惰性数据结构是可行的并且工作得很好.这将导致以下实例:
data MemTree = MemNode [Key] [MemTree]
| MemLeaf [Key] [Data]
Run Code Online (Sandbox Code Playgroud)
现在我的目标是创建一个通用函数updateFile :: FilePath -> (MemTree -> MemTree) -> IO (),将其读入FileTree并转换为MemTree,应用该MemTree -> MemTree函数并将更改写回树结构.问题是必须以某种方式保存FileOffsets.
我有两种解决这个问题的方法.他们都缺乏优雅和/或效率:
这种方法扩展了MemTree以包含偏移量:
data MemTree = MemNode [Key] [(MemTree, Maybe FileOffset)]
| MemNode [Key] [Data]
Run Code Online (Sandbox Code Playgroud)
然后读取函数将读入FileTree并存储FileOffset在MemTree引用旁边.写入将检查引用是否已经具有关联的偏移量,如果它已经有,则仅使用它.
优点:易于实现,无需开销即可找到偏移量
缺点:暴露负责设置偏移的用户的内部Nothing
解决这个问题的另一种方法是读入FileTree并创建一个StableName.Map保留在FileOffsets …
我在考虑安全Haskell,我想知道我有多信任它?
我是一个编写可编程游戏的小黑客(想想Robocode),我允许其他人编写自己的实体来互相竞争.大多数情况下,用户将在私人计算机上运行一些不受信任的程序.在运行之前可能会检查不受信任的代码.
我是几个客户使用的应用程序的程序员.我提供了一个API,以便他们可以扩展功能并鼓励我的用户分享他们的插件.用户社区规模很小,大部分时间都存在相互信任,但有时候有人正在开展一个绝密的客户项目,任何数据泄漏都将是灾难性的.
我是...谷歌(或Facebook,雅虎等),并希望允许我的客户编写他们的电子邮件帐户脚本.脚本已上载并在我的服务器上运行.任何访问违规都是致命的.
我目前正在探索使用基本容器为FRP网络提供更多结构的可能性,从而更容易创建更复杂的事件网络.
注意:我使用ordrea但反应性香蕉也有同样的问题,所以我想这个问题不是特定于所选的frp实现.
在这个特殊情况下,我使用一个简单Matrix的存储Events:
newtype Matrix (w :: Nat) (h :: Nat) v a where
Matrix :: Vector a -> Matrix w h v a
-- deriving instances: Functor, Foldable, Traversable, Applicative
Run Code Online (Sandbox Code Playgroud)
Matrix基本上只是一个薄的包装器Data.Vector,我将使用的大多数功能基本上与相应Vector的功能相同.值得注意的例外是索引,但这应该是自我解释的.
有了这个,我可以定义事件的矩阵,Matrix 10 10 (Event Double)并且能够定义基本的卷积算法:
applyStencil :: (KnownNat w, KnownNat h, KnownNat w', KnownNat h')
=> M.Matrix w' h' (a -> c)
-> M.Matrix w h (Event a)
-> M.Matrix w h …Run Code Online (Sandbox Code Playgroud) 我只是写了这样的函数,map4因为它们似乎很有用:
map2 :: Functor f => (i -> a) -> (i -> b) -> f i -> f (a,b)
map2 f1 f2 = fmap $ \i -> (f1 i, f2 i)
Run Code Online (Sandbox Code Playgroud)
在我继续之前,map8我想我会问一些标准模块中是否有类似的东西.Hayoo似乎不知道任何具有上述签名的功能.
注意:我已经发现Control.Arrow.&&&将上述内容减少到:
map2 f1 f2 = fmap (f1 &&& f2)
Run Code Online (Sandbox Code Playgroud)
但是,对于超过两个的扇出似乎没有类似的功能.
是否有任何隐藏的选项将成本中心放入图书馆?目前我已经设置了这样的分析:
ghc-prof-options: -O2
-threaded
-fexcess-precision
-fprof-auto
-rtsopts
"-with-rtsopts=-N -p -s -h -i0.1"
Run Code Online (Sandbox Code Playgroud)
# cabal sandbox init
# cabal install --enable-library-profiling --enable-executable-profiling
# cabal configure --enable-library-profiling --enable-executable-profiling
# cabal run
Run Code Online (Sandbox Code Playgroud)
这可以在程序完成时创建预期的.prof文件,.hp文件和摘要.
问题是该.prof文件不包含任何不属于当前项目的内容.我的猜测是,可能有一个选项可以将成本中心放在外部库代码中?
haskell ×10
frp ×2
aeson ×1
arrows ×1
cabal ×1
catamorphism ×1
conduit ×1
fold ×1
free-monad ×1
fusion ×1
idris ×1
iterate ×1
kdtree ×1
optimization ×1
overloading ×1
record ×1
sandbox ×1