Forwarded from dnaugsuz
这方面最典型的例子就是停机问题
当然计算机科学的研究者们是不肯把程序写成这样的,不过还是可以有 Y 组合子……
halting p = if p then infinity else 1这种情况就是 True -> (没有值); False -> Int
where
infinity = drop Infinity ones
ones = 1 : ones
当然计算机科学的研究者们是不肯把程序写成这样的,不过还是可以有 Y 组合子……
Y = \f. (\c. f (c c)) (\c. f (c c))Forwarded from dnaugsuz
Tcl/tk 嘛(读 tickle)
我觉得它和 Squirrel 一样,没点文档
我觉得它和 Squirrel 一样,没点文档
Forwarded from dnaugsuz
我讨厌文档不好的语言;Lua 可是一个类似但文档很好的语言
Forwarded from dnaugsuz
所以说我其实是一个倾向工程派的人,因为我简直无法忍受学术系 Haskell 的风格,都快无法结合那一堆 phi psi mu (>>=) ($) 了……
但我一点都不觉得函数式能够解决更多问题,实际上我只是喜欢混合函数式编程的风格,和纯函数控制那一套无关
但我一点都不觉得函数式能够解决更多问题,实际上我只是喜欢混合函数式编程的风格,和纯函数控制那一套无关
Forwarded from awasarihS
其实讲道理咱想写个kt到ts的compiler 就是没看懂它这个inline是咋实现的
Forwarded from dnaugsuz
套一下呗,举个栗子:
现在你得到了 AST:
于是你可以 inline:
然后就内联上了,最终代码是这种形式:
是等价的
inline fun justA1M2(x: Int) = (x + 1) * 2
fun logic() {
val y = justA1M2(0)
println(y)
} 现在你得到了 AST:
inline fn [justA1M2]
argt: (Formal (Name x) (Type Int))
body: (Expr (InfixChain (Op* (Op+ (NamedRef 'x) (Lit 1) ) 2))
fn [logic]
argt:
locals: (Val 'y (Type Int))
body: (CompStmt[
(Assign (NamedRef 'y) (Call 'justA1M2 [(Lit 0)]))
(ExprStmt (Call 'println [(NamrdRef 'y)]))
]) 于是你可以 inline:
body: (CompStmt[
(Assign (NamedRef 'y) (Call 'justA1M2 [0])) -- 注意这里,你调用了 inline fn
然后直接以表达式的形式 subtract(替换): body: (CompStmt[
-- (Assign (NamedRef 'y) (Call 'justA1M2 [(Lit 0)]))
(Assign (NamedRef 'y) (Expr (InfixChain (Op* (Op+ (Inlined (Lit 0)) (Lit 1) ) 2)))
(ExprStmt (Call 'println [(NamrdRef 'y)]))
]) 然后就内联上了,最终代码是这种形式:
fun logic() {
val y = /*justA1M2(0)*/ @Source(…) (0 + 1) * 2
println(y)
} 是等价的
Forwarded from dnaugsuz
你的意思是…… 哪个栗子
Forwarded from ❌; Ζέφυρος Λύκος
> 兴趣和简明的第一印象,远比定义是否准确更重要吧
我觉得定义是否准确也挺重要的
假定 ta 来问你问题,你回复的是一个简明但模糊的概念(当然这不是要包山包海什么都讲),日后 ta 开始感兴趣深入了解,(手机打字慢等会x)
我觉得定义是否准确也挺重要的
假定 ta 来问你问题,你回复的是一个简明但模糊的概念(当然这不是要包山包海什么都讲),日后 ta 开始感兴趣深入了解,(手机打字慢等会x)
Forwarded from ❌; Ζέφυρος Λύκος
(接)发现与自己原有建立的知识体系不一样是,一般会有两种反应
1) 有耐心的会仔细看完文档,最后想到你为什么会这么回答 ta(当然是要花费大量的精力去弄懂这些「软件包格式」「Daivlk 虚拟机」「ObjC」等等),初学者就更不用说,更多的则是下面的情况
2) 没耐心的有的是放弃对这些事的信心,偏激一点的对你的答复不满意,反而起到相反作用,甚至觉得「屁事真多」想法,更不敢接触了
1) 有耐心的会仔细看完文档,最后想到你为什么会这么回答 ta(当然是要花费大量的精力去弄懂这些「软件包格式」「Daivlk 虚拟机」「ObjC」等等),初学者就更不用说,更多的则是下面的情况
2) 没耐心的有的是放弃对这些事的信心,偏激一点的对你的答复不满意,反而起到相反作用,甚至觉得「屁事真多」想法,更不敢接触了
Forwarded from dnaugsuz
有些事情就是不能不慢慢理解的……
小时候我妈问我一个问题,『一千克棉花和一千克钢铁哪个重』
我一下就答错了,而且他们怎么教我也还是觉得钢铁重……
其实当时就是真的不知道『重』这个修饰是什么意思,后来一年多以后才能明白。
对心智成熟的成年人来说也是一样的。
小时候我妈问我一个问题,『一千克棉花和一千克钢铁哪个重』
我一下就答错了,而且他们怎么教我也还是觉得钢铁重……
其实当时就是真的不知道『重』这个修饰是什么意思,后来一年多以后才能明白。
对心智成熟的成年人来说也是一样的。
Forwarded from dnaugsuz
我就是那个意思,有些事情是需要时间
Forwarded from dnaugsuz
学习是很佛系的一件事情,尤其是不被高考所迫的情况下
Forwarded from dnaugsuz
他不愿意学,你怎么弄也没用,除非你真的很厉害……
所以要学习的话就只能慢慢来,或许今天你非常生气,后来莫名其妙就理解了。
所以要学习的话就只能慢慢来,或许今天你非常生气,后来莫名其妙就理解了。
#dev 按照预期,今天晚上我还会讲关于我这周一个 Infix 链解析优化的算法、关于 RangeMap 的扩展 — OverlapRangeMap 的一些实现 note。
本周 #school 是月假;本来是还要写 Montage 图 Python 和 Dijkstra 同类的算法的,但是由于 Parser.kt 和 Binarie 更为重要,所以我不保证它们可以被有效执行。
不过我得先分享一些东西 — 比较方便的 IDEA 快捷键
== 代码浏览
上/下个方法: (Alt+ArrowUp / Alt+ArrowDown)
查看文档: Ctrl + Q
查看简明实现: Ctrl+Shift + I
查看表达式类型: Ctrl+Shift + P
跳转到符号: Ctrl + MouseL, Ctrl + B
跳转到类型定义: Ctrl+Shift + B
跳转到测试: Ctrl + T
== IDE 基本
文件菜单: Alt + F
Search everywhere: Ctrl + N
执行当前任务: Shift+F10
调试当前任务: Shift+F9
== Editor 基本
indent:
-: Shift + Tab
+: Tab (皆可按选区操作)
dup line: Ctrl + D
join lines: Ctrl+Shift + J
== 代码
快速模板: Ctrl + J
以快速模板包围: Ctrl+Alt + J
自动缩进/优化导入: (Ctrl+Alt + I / Ctrl+Alt + O)
自动布局: Alt+Shift + R
自动包围: Ctrl+Alt + T
自动去除包围: Ctrl+Alt+Shift + T
自动生成: Alt+Insert
自动重写/实现: (Ctrl+O / Ctrl+I)
手动唤起自动补齐: Ctrl + Space
类型敏感自动补齐: Ctrl+Shift + Space
== 重构
快捷菜单: Ctrl+Alt+Shift+T
上/下移语句: (Ctrl+Shift + ArrowUp / Ctrl+Shift + ArrowDown)
重命名: Shift+F6
改变方法签名: Ctrl+6
到变量/方法: (Alt+Shift+V / Ctrl+Alt+M)
== 分析
文件树: Ctrl + 0
继承树: Ctrl + H
方法调用树: Ctrl + Alt + H
查找引用: Alt+Shift + 7
本周 #school 是月假;本来是还要写 Montage 图 Python 和 Dijkstra 同类的算法的,但是由于 Parser.kt 和 Binarie 更为重要,所以我不保证它们可以被有效执行。
不过我得先分享一些东西 — 比较方便的 IDEA 快捷键
== 代码浏览
上/下个方法: (Alt+ArrowUp / Alt+ArrowDown)
查看文档: Ctrl + Q
查看简明实现: Ctrl+Shift + I
查看表达式类型: Ctrl+Shift + P
跳转到符号: Ctrl + MouseL, Ctrl + B
跳转到类型定义: Ctrl+Shift + B
跳转到测试: Ctrl + T
== IDE 基本
文件菜单: Alt + F
Search everywhere: Ctrl + N
执行当前任务: Shift+F10
调试当前任务: Shift+F9
== Editor 基本
indent:
-: Shift + Tab
+: Tab (皆可按选区操作)
dup line: Ctrl + D
join lines: Ctrl+Shift + J
== 代码
快速模板: Ctrl + J
以快速模板包围: Ctrl+Alt + J
自动缩进/优化导入: (Ctrl+Alt + I / Ctrl+Alt + O)
自动布局: Alt+Shift + R
自动包围: Ctrl+Alt + T
自动去除包围: Ctrl+Alt+Shift + T
自动生成: Alt+Insert
自动重写/实现: (Ctrl+O / Ctrl+I)
手动唤起自动补齐: Ctrl + Space
类型敏感自动补齐: Ctrl+Shift + Space
== 重构
快捷菜单: Ctrl+Alt+Shift+T
上/下移语句: (Ctrl+Shift + ArrowUp / Ctrl+Shift + ArrowDown)
重命名: Shift+F6
改变方法签名: Ctrl+6
到变量/方法: (Alt+Shift+V / Ctrl+Alt+M)
== 分析
文件树: Ctrl + 0
继承树: Ctrl + H
方法调用树: Ctrl + Alt + H
查找引用: Alt+Shift + 7
duangsuse::Echo
#dev 按照预期,今天晚上我还会讲关于我这周一个 Infix 链解析优化的算法、关于 RangeMap 的扩展 — OverlapRangeMap 的一些实现 note。 本周 #school 是月假;本来是还要写 Montage 图 Python 和 Dijkstra 同类的算法的,但是由于 Parser.kt 和 Binarie 更为重要,所以我不保证它们可以被有效执行。 不过我得先分享一些东西 — 比较方便的 IDEA 快捷键 == 代码浏览 上/下个方法: (Alt+ArrowUp / Alt+ArrowDown)…
如果你实在记不住,应当先记这些:
== 基础浏览和编辑
Alt+Up/Alt+Down
Ctrl+D/Ctrl+J
Ctrl+Space
Ctrl+T
Ctrl+N
== 文档
Ctrl+Q
Ctrl+Shift+I
Ctrl+Shift+P
== 模板
Ctrl+J / Ctrl+Alt+J
Ctrl+Alt+T
Alt+Insert
== 基本重构
Ctrl+F6
Ctrl+6
Ctrl+Alt+Shift+T
Ctrl+Shift+Up / Ctrl+Shift+Down
Alt+Shift+V / Ctrl+Alt+M
== 基本分析
Ctrl+0
Ctrl+Alt+H
== IDE 任务
Ctrl+9
Shift+F10
Shift+F9
当然这些都是可以自定义的,我说的是默认布局。
== 基础浏览和编辑
Alt+Up/Alt+Down
Ctrl+D/Ctrl+J
Ctrl+Space
Ctrl+T
Ctrl+N
== 文档
Ctrl+Q
Ctrl+Shift+I
Ctrl+Shift+P
== 模板
Ctrl+J / Ctrl+Alt+J
Ctrl+Alt+T
Alt+Insert
== 基本重构
Ctrl+F6
Ctrl+6
Ctrl+Alt+Shift+T
Ctrl+Shift+Up / Ctrl+Shift+Down
Alt+Shift+V / Ctrl+Alt+M
== 基本分析
Ctrl+0
Ctrl+Alt+H
== IDE 任务
Ctrl+9
Shift+F10
Shift+F9
当然这些都是可以自定义的,我说的是默认布局。
ParserKt 已经在设计上准备好进行第一次重写,这次重写会包含以下内容:
+ 针对 BulkFeeder 什么的;lineNumber 只能是 LF/CR/CRLF 中的一种,不可能在 Feeder 层面同时兼容
+ 对类似 ParsingFeeder、TreeRangeMap 的结构,开放一些辅助方法的覆写以提升代码重用性
+ 提供 reduceOr 和 leftrec 特性(左递归文法支持)
+ 针对基于 Buffer 的 MarkReset,它的 stack 必须是 lazily evaluated [
+ takeWhile 和 dropWhile 会被重命名为 takeTerminate; skipTerminate,FeederOpt 里的 takeUntilIn, skipWhileIn 重命名。
+ Folder 架构会有更多实例,比如
基本的原子解析器会被定义为内联的
+ 会加入很多扩展的内联解析修饰 (pre, effect, …)
+ Box<T> (就是可空版的 Maybe)会被正式包装好,也包括 map/flatMap 操作
+ 针对 BulkFeeder 什么的;lineNumber 只能是 LF/CR/CRLF 中的一种,不可能在 Feeder 层面同时兼容
+ 对类似 ParsingFeeder、TreeRangeMap 的结构,开放一些辅助方法的覆写以提升代码重用性
+ 提供 reduceOr 和 leftrec 特性(左递归文法支持)
+ 针对基于 Buffer 的 MarkReset,它的 stack 必须是 lazily evaluated [
newBuffer()],这意味着 Parser.tryRun(Feeder) 的子解析器如果没有实际上 consume() 一些项目,就不会有调用架构器的开销+ takeWhile 和 dropWhile 会被重命名为 takeTerminate; skipTerminate,FeederOpt 里的 takeUntilIn, skipWhileIn 重命名。
+ Folder 架构会有更多实例,比如
asHist(), asCount()
+ 很多原子解析器都会被重命名: char(_), anyChar, charSatisfies, charIn, charseq…基本的原子解析器会被定义为内联的
+ 会加入很多扩展的内联解析修饰 (pre, effect, …)
+ Box<T> (就是可空版的 Maybe)会被正式包装好,也包括 map/flatMap 操作
在我证明了它可以解析 JSON 和 Kotlin 之后,我就会抛弃现在叫 jison 的 ParserKt;完全重写 ParserKt
新的库会更加模块化、更简单,并且会实现这次没有实现的 source map 和
新的库会更加模块化、更简单,并且会实现这次没有实现的 source map 和
clamDown 镇定解析策略。老版本的 ParserKt 不会维持多久的,它有太多的问题;尽管有不少代码都是好的,但是依然需要彻底脱胎重构、去除冗杂和莫名其妙的设计
#Haskell 里定义类型的一些方式:
当然,一般它是和 Record 架解构同用的
这是代数数据类型 (Algebraic Data Types)
这样的 Lambda 看起来是这样…… 当然也可以
(Generalized Algebraic DataTypes,也就是「广义」的代数数据类型)
它有两个架构器
最基本的情况,GADT 允许你直接写明架构器们的类型,当然这对类型系统是有用的,一般用来实现EDSL(Embedded Domain Specific Language)的AST(Abstract Syntax Tree),不过是受更强类型检查的那种。
(Scala)
它的意思是,T 只是用来确定 Link 里那个 T,和后面它的子类架构器的各种 T 无关:
所以我们的
如果不呢?
因为没有限制你也不可以保证
实际上
这就是 GADT 的作用,当然在 Kotlin 的类型系统里是不存在这类问题的,除非你要
以上描述会比
https://blog.hoshino9.org/2019/07/26/how-to-create-a-wonderful-type.html
的直白一些,用的概念也都是 Haskell 原生的(数据、数据架构器),而不是从 C++ 系套过来方便理解的(枚举…)
因为一方面,我觉得你把『类型』视为它『数据实例』的集合,然后取交(&,inersection)并(|,union)都不会的话,也就不要学 Haskell 了……
另一方面,从引文也可以看到如果要用 C++ 那一套的话,你会像数学一样弄出一大堆
甚至你还可以弄出『带参数且只有一个值和一个case的枚举类型』……
说实话,这就是基本编程思想问题而已:是用
当然 Haskell 里的是最直白的,Haskell 的类型就是单纯的类型…… 不要把你用
type Ints = [Int] — type synonym
newtype User = User (String, Int) — newtype
newtype 就是「new」了的「type synonym」,exactly one constructor, exactly one field.当然,一般它是和 Record 架解构同用的
newtype User = User { name :: String, age :: Int }
不要把它和 Monad 扯上关系。data User = User String Int | Monkey Int — data declaration 这是代数数据类型 (Algebraic Data Types)
id (User name age) = User name age解构等式定义,等号后面访问到的 name 是 User 的第一个 field
(name :: String)、age :: Int
(\(User no yo) -> (no, yo)) :: User -> (String, Int) 这样的 Lambda 看起来是这样…… 当然也可以
let (no, yo) = user in … 解构data Link a where这是 GADT (-XGADTs)
Cons :: a -> Link a -> Link a
Nil :: Link a
(Generalized Algebraic DataTypes,也就是「广义」的代数数据类型)
它有两个架构器
(Cons h tail) 和 Nil (对面向对象来说就是子类型的架构器……)最基本的情况,GADT 允许你直接写明架构器们的类型,当然这对类型系统是有用的,一般用来实现EDSL(Embedded Domain Specific Language)的AST(Abstract Syntax Tree),不过是受更强类型检查的那种。
data Link a = Cons a (Link a) | Nil对于这种情况 (Kotlin)
sealed class Link<out T> {
data class Cons(val head: T, val tail: Link<T>): Link<T>()
object Nil: Link<Nothing>()
} (Scala)
trait Link[+T]不过这里我们没直接用 GADT 们独有的特性,只是说,
case class Cons[T](x: T) extends Link[T]
case object Nil extends Link[Nothing]
Link[T] 的这个 type variable T
被人称为「phantom type variable」(dummy 的 typevar)它的意思是,T 只是用来确定 Link 里那个 T,和后面它的子类架构器的各种 T 无关:
{-# LANGUAGE GADTs #-}
data Ast a where
I :: Int -> Ast Int
P :: Bool -> Ast Bool
And :: Ast a -> Ast a -> Ast a
(差点忍不住手痒把 type InfixCons t = t -> t -> t 抽提了…… Kotlin 里面可没有 Higher Kinds, type constructors 这么方便的东西啊,只能参数化多态)所以我们的
(I 1) :: Ast Int,但 (And (I 1) (I 2)) 也是 Ast Int……(跑如果不呢?
data Ast a = I Int | P Bool | And (Ast a) (Ast a)
And :: forall a. Ast a -> Ast a -> Ast a (P True, I 2) 是什么?如果把他们取一个并集(union) 你会发现他们都是 forall a. Ast a…… 这个该死的 "unbound" 类型变量 a
And (P True) (I 2) :: Ast a 于是,你就可以得到一个完全无关的 Ast 类型因为没有限制你也不可以保证
And (P p0) (I x) 不出现,Haskell 的 type checker 也不能保证(定义解构函数的时候)实际上
(P True) :: (Ast String) 都可以,因为你 :type P 会发现它只是 forall a. P :: Bool -> Ast a,这是属于比较骚操作的情况了。这就是 GADT 的作用,当然在 Kotlin 的类型系统里是不存在这类问题的,除非你要
Cons<T>(…): Link<out Nothing>() 以上描述会比
https://blog.hoshino9.org/2019/07/26/how-to-create-a-wonderful-type.html
的直白一些,用的概念也都是 Haskell 原生的(数据、数据架构器),而不是从 C++ 系套过来方便理解的(枚举…)
因为一方面,我觉得你把『类型』视为它『数据实例』的集合,然后取交(&,inersection)并(|,union)都不会的话,也就不要学 Haskell 了……
另一方面,从引文也可以看到如果要用 C++ 那一套的话,你会像数学一样弄出一大堆
XX类型 这种带修饰的名词…… 比如『枚举数据类型』、『只有一个值的枚举类型』、『带有参数的枚举类型』……甚至你还可以弄出『带参数且只有一个值和一个case的枚举类型』……
说实话,这就是基本编程思想问题而已:是用
Desc(x: String?) 还是 Desc(x: String) | NoDesc?我觉得必须看情况来择一而取。当然 Haskell 里的是最直白的,Haskell 的类型就是单纯的类型…… 不要把你用
data 定义的那一套当作『类型』…… 因为 Haskell 还有很多种『类型』足够打脸……blog.hoshino9.org
Haskell 如何打造爆款数据类型
数据类型是 Haskell 中的重要知识之一这篇文章讲教你从一无所知到随手打造爆款数据类型