我已经读过没有foldl单独的融合法.如果我猜对了,这是由于foldl实施地图的尴尬 - 这主要是由于(foldl cons nil xs)反转列表.
如果我们使用conc列表,那么foldlmap这个方面的功能要好得多:
(foldlmap list conc nil xs) -> xs
Run Code Online (Sandbox Code Playgroud)
如果我的猜测是正确的,那么应该有一个简单的融合法foldlmap.它是否正确?
我读过一些monads tutoriais,他们几乎提出monad是实现操作顺序所必需的.但同样可以通过以下方式实现let:
(let*
( (a 1)
(b (+ a 1))
(c (+ b 1)))
c)
Run Code Online (Sandbox Code Playgroud)
被禁止(实际上,我为了说明目的写了这个脑谜,请参阅Will Ness的评论):
((lambda (c) c)
((lambda (b) (+ b 1))
((lambda (a) (+ a 1))
1)))
Run Code Online (Sandbox Code Playgroud)
那么如果这个宏能够实现排序,那么如何实现排序需要monad呢?
以下函数返回从根节点到树的最深节点的可能路径列表:
paths :: Tree a -> [[a]]
paths (Node element []) = [[element]]
paths (Node element children) = map (element :) $ concat $ map paths children
Run Code Online (Sandbox Code Playgroud)
这在纸面上看起来非常低效,因为它concat具有可怕的复杂性.是否可以在不使用中间数据结构(如序列)的情况下以较低的复杂度重写此函数?
编辑:说实话,我知道可以通过以下方式避免连接的O(n)/循环复杂性:
这是一个JavaScript实现,说明了这个算法:
function paths(tree){
var result = [];
(function go(node,path){
if (node.children.length === 0)
result.push(path.concat([node.tag]));
else
node.children.map(function(child){
go(child,path.concat([node.tag]));
});
})(tree,[]);
return result;
}
console.log(paths(
{tag: 1,
children:[
{tag: 2, children: [{tag: 20, children: []}, {tag: 200, children: []}]},
{tag: 3, children: [{tag: 30, children: []}, {tag: 300, children: …Run Code Online (Sandbox Code Playgroud) GHC在这一点上的速度惊人地快.不过,我对Haskell的类型系统不满意,所以我决定将自己的系统作为DSL来实现.现在,我想通过翻译后检查无类型lambda演算表达式来编译我的语言到Haskell,以便使用GHC的性能.唯一的问题是我的系统上的某些有效表达式无法在GHC上编译.我怎样才能避免这个问题 - 即通过告诉GHC完全禁用类型系统"我已经检查了这个,相信我"?
这是我的代码:
import Data.Function.Memoize
import Debug.Trace
foo :: Int -> Int -> Int
foo a = memoFix fooMemo where
fooMemo f x = a + (trace (show x) cont) where
cont = if x == 0 then 0 else x + f (x - 1)
main = do
print $ foo 0 5
print $ foo 0 5
print $ foo 0 5
Run Code Online (Sandbox Code Playgroud)
我希望它打印:
3
2
1
0
6
6
6
Run Code Online (Sandbox Code Playgroud)
但是,它打印出来:
3
2
1
0
6
3
2
1
0 …Run Code Online (Sandbox Code Playgroud) 这是标准的Hello World CUDA文件:
#include <stdio.h>
#include "hello.h"
const int N = 7;
const int blocksize = 7;
__global__ void hello_kernel(char *a, int *b) {
a[threadIdx.x] += b[threadIdx.x];
}
#define cudaCheckError() { \
cudaError_t e=cudaGetLastError(); \
if(e!=cudaSuccess) { \
printf("Cuda failure %s:%d: '%s'\n",__FILE__,__LINE__,cudaGetErrorString(e)); \
exit(0); \
} \
}
void hello() {
char a[N] = "Hello ";
int b[N] = {15, 10, 6, 0, -11, 1, 0};
char *ad;
int *bd;
const int csize = N*sizeof(char);
const int isize = N*sizeof(int); …Run Code Online (Sandbox Code Playgroud) 我正在研究λ演算的最佳实现.有一个特定的lambda术语子集是非常有效的.它对应于具有固定点的基本仿射逻辑的类型系统.为了测试我对该算法的实现,我必须在该系统上编写适度复杂的术语.没有基础设施,这很困难.我必须使用无类型的lambda演算,然后手动添加类型; 没有检查,统一,没有类型错误.
一个想法是在Haskell中编写程序 - 从其成熟的类型检查器中获益 - 然后转换为EAL.不幸的是,System-Fw和EAL之间存在不匹配.例如,newtype由于缺少类型级别,您无法在Haskell中表达Scott编码的ADT fix.而且,Haskell是一种复杂的语言,编写Haskell->EAl编译器并不是一件容易的事.
有没有快速/脏的方法来获得该系统的工作类型检查器/推理器/统一器 - 或者至少足够接近 - 而不必自己编程?
是否存在在两种数据类型之间创建双射的策略?例如,考虑以下数据类型:
data Colbit
= White Colbit Colbit
| Black Colbit Colbit
| Tip
data Bits
= B0 Bits
| B1 Bits
| BEnd
Run Code Online (Sandbox Code Playgroud)
加上有效元素Colbit必须具有奇数个节点(白/黑构造函数)的约束.我该如何创建地图:
toColbit :: Bits -> Colbit
fromColbit :: Colbit -> Bits
Run Code Online (Sandbox Code Playgroud)
这样,对所有人b : Bits,fromColbit (toColbit b) == b对所有人来说c : Colbit,toColbit (fromColbit c) == c?(另外,这个属性叫什么?)
以下代码在Go中实现了一个int列表:
package main
import "fmt"
type List struct {
Head int
Tail *List
}
func tail(list List) *List {
return list.Tail
}
func main() {
list := List{Head: 1, Tail:
&List{Head: 2, Tail:
&List{Head: 3, Tail:
nil}}}
fmt.Println(tail(list).Head)
}
Run Code Online (Sandbox Code Playgroud)
问题是这只适用于int.如果我想要一个列表strings,我需要再次重新实现每个列表方法(例如tail)!这显然不实用,所以,这可以通过使用空接口来解决:
type List struct {
Head interface{} // Now works for any type!
Tail *List
}
Run Code Online (Sandbox Code Playgroud)
问题是,1.由于类型转换,这似乎要慢得多,2.它抛弃了类型安全,允许人们键入任何东西:
// This type-checks!
func main() {
list := List{Head: 123456789 , Tail:
&List{Head: "covfefe" , Tail: …Run Code Online (Sandbox Code Playgroud) 当试图mod : Nat -> (m : Nat) -> Fin m在 Idris上实现一个函数时,我注意到明显的算法不起作用,因为当循环和增加结果时,Idris 不会相信它仍在范围内。这段代码解释了这个问题:
-- (M : Nat) is the modulus, doesn't change
-- (r : Fin M) is the result, increases as you recurse
-- (n : Nat) is the dividend, the recursion stops when it is 0
-- (m : Nat) is the modulus index, when it is Zero, the result loops around
modAux : (M : Nat) -> (r : Fin M) -> (n : Nat) -> …Run Code Online (Sandbox Code Playgroud)