roc/test/snapshots/lambda_currying_constraint.md
2025-11-19 10:31:11 -05:00

5 KiB

META

description=Lambda currying with polymorphic function constraints - tests if numeric literals in curried functions get properly constrained
type=snippet

SOURCE

# Function that returns a function with polymorphic type
makeAdder : a -> (a -> a)
makeAdder = |x| |y| x + y

# Should constrain the literal 5 to I64
curriedAdd : I64 -> I64
curriedAdd = makeAdder(5)

# Higher-order function that applies a function twice
applyTwice : (a -> a), a -> a
applyTwice = |f, x| f(f(x))

# Should constrain the literal 3 to I64
addThreeTwice : I64 -> I64
addThreeTwice = |n| applyTwice(|x| x + 3, n)

EXPECTED

NIL

PROBLEMS

NIL

TOKENS

LowerIdent,OpColon,LowerIdent,OpArrow,OpenRound,LowerIdent,OpArrow,LowerIdent,CloseRound,
LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,OpBar,LowerIdent,OpBar,LowerIdent,OpPlus,LowerIdent,
LowerIdent,OpColon,UpperIdent,OpArrow,UpperIdent,
LowerIdent,OpAssign,LowerIdent,NoSpaceOpenRound,Int,CloseRound,
LowerIdent,OpColon,OpenRound,LowerIdent,OpArrow,LowerIdent,CloseRound,Comma,LowerIdent,OpArrow,LowerIdent,
LowerIdent,OpAssign,OpBar,LowerIdent,Comma,LowerIdent,OpBar,LowerIdent,NoSpaceOpenRound,LowerIdent,NoSpaceOpenRound,LowerIdent,CloseRound,CloseRound,
LowerIdent,OpColon,UpperIdent,OpArrow,UpperIdent,
LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,LowerIdent,NoSpaceOpenRound,OpBar,LowerIdent,OpBar,LowerIdent,OpPlus,Int,Comma,LowerIdent,CloseRound,
EndOfFile,

PARSE

(file
	(type-module)
	(statements
		(s-type-anno (name "makeAdder")
			(ty-fn
				(ty-var (raw "a"))
				(ty-fn
					(ty-var (raw "a"))
					(ty-var (raw "a")))))
		(s-decl
			(p-ident (raw "makeAdder"))
			(e-lambda
				(args
					(p-ident (raw "x")))
				(e-lambda
					(args
						(p-ident (raw "y")))
					(e-binop (op "+")
						(e-ident (raw "x"))
						(e-ident (raw "y"))))))
		(s-type-anno (name "curriedAdd")
			(ty-fn
				(ty (name "I64"))
				(ty (name "I64"))))
		(s-decl
			(p-ident (raw "curriedAdd"))
			(e-apply
				(e-ident (raw "makeAdder"))
				(e-int (raw "5"))))
		(s-type-anno (name "applyTwice")
			(ty-fn
				(ty-fn
					(ty-var (raw "a"))
					(ty-var (raw "a")))
				(ty-var (raw "a"))
				(ty-var (raw "a"))))
		(s-decl
			(p-ident (raw "applyTwice"))
			(e-lambda
				(args
					(p-ident (raw "f"))
					(p-ident (raw "x")))
				(e-apply
					(e-ident (raw "f"))
					(e-apply
						(e-ident (raw "f"))
						(e-ident (raw "x"))))))
		(s-type-anno (name "addThreeTwice")
			(ty-fn
				(ty (name "I64"))
				(ty (name "I64"))))
		(s-decl
			(p-ident (raw "addThreeTwice"))
			(e-lambda
				(args
					(p-ident (raw "n")))
				(e-apply
					(e-ident (raw "applyTwice"))
					(e-lambda
						(args
							(p-ident (raw "x")))
						(e-binop (op "+")
							(e-ident (raw "x"))
							(e-int (raw "3"))))
					(e-ident (raw "n")))))))

FORMATTED

NO CHANGE

CANONICALIZE

(can-ir
	(d-let
		(p-assign (ident "makeAdder"))
		(e-lambda
			(args
				(p-assign (ident "x")))
			(e-closure
				(captures
					(capture (ident "x")))
				(e-lambda
					(args
						(p-assign (ident "y")))
					(e-binop (op "add")
						(e-lookup-local
							(p-assign (ident "x")))
						(e-lookup-local
							(p-assign (ident "y")))))))
		(annotation
			(ty-fn (effectful false)
				(ty-rigid-var (name "a"))
				(ty-parens
					(ty-fn (effectful false)
						(ty-rigid-var-lookup (ty-rigid-var (name "a")))
						(ty-rigid-var-lookup (ty-rigid-var (name "a"))))))))
	(d-let
		(p-assign (ident "curriedAdd"))
		(e-call
			(e-lookup-local
				(p-assign (ident "makeAdder")))
			(e-num (value "5")))
		(annotation
			(ty-fn (effectful false)
				(ty-lookup (name "I64") (builtin))
				(ty-lookup (name "I64") (builtin)))))
	(d-let
		(p-assign (ident "applyTwice"))
		(e-lambda
			(args
				(p-assign (ident "f"))
				(p-assign (ident "x")))
			(e-call
				(e-lookup-local
					(p-assign (ident "f")))
				(e-call
					(e-lookup-local
						(p-assign (ident "f")))
					(e-lookup-local
						(p-assign (ident "x"))))))
		(annotation
			(ty-fn (effectful false)
				(ty-parens
					(ty-fn (effectful false)
						(ty-rigid-var (name "a"))
						(ty-rigid-var-lookup (ty-rigid-var (name "a")))))
				(ty-rigid-var-lookup (ty-rigid-var (name "a")))
				(ty-rigid-var-lookup (ty-rigid-var (name "a"))))))
	(d-let
		(p-assign (ident "addThreeTwice"))
		(e-closure
			(captures
				(capture (ident "applyTwice")))
			(e-lambda
				(args
					(p-assign (ident "n")))
				(e-call
					(e-lookup-local
						(p-assign (ident "applyTwice")))
					(e-lambda
						(args
							(p-assign (ident "x")))
						(e-binop (op "add")
							(e-lookup-local
								(p-assign (ident "x")))
							(e-num (value "3"))))
					(e-lookup-local
						(p-assign (ident "n"))))))
		(annotation
			(ty-fn (effectful false)
				(ty-lookup (name "I64") (builtin))
				(ty-lookup (name "I64") (builtin))))))

TYPES

(inferred-types
	(defs
		(patt (type "a -> (a -> a)"))
		(patt (type "I64 -> I64"))
		(patt (type "(a -> a), a -> a"))
		(patt (type "I64 -> I64")))
	(expressions
		(expr (type "a -> (a -> a)"))
		(expr (type "I64 -> I64"))
		(expr (type "(a -> a), a -> a"))
		(expr (type "I64 -> I64"))))