2023-07-23 22:05:54 +02:00
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2023-07-14 17:30:58 +02:00
package cli
import (
"fmt"
"os"
"strings"
)
2023-07-21 10:55:03 +02:00
func tupleType ( name string ) func ( i int ) string {
return func ( i int ) string {
var buf strings . Builder
buf . WriteString ( fmt . Sprintf ( "T.Tuple%d[" , i ) )
for j := 0 ; j < i ; j ++ {
if j > 0 {
buf . WriteString ( ", " )
}
buf . WriteString ( fmt . Sprintf ( "%s%d" , name , j + 1 ) )
2023-07-14 17:30:58 +02:00
}
2023-07-21 10:55:03 +02:00
buf . WriteString ( "]" )
2023-07-14 17:30:58 +02:00
2023-07-21 10:55:03 +02:00
return buf . String ( )
}
2023-07-14 17:30:58 +02:00
}
func monadGenerateSequenceTNonGeneric (
hkt func ( string ) string ,
fmap func ( string , string ) string ,
fap func ( string , string ) string ,
) func ( f * os . File , i int ) {
return func ( f * os . File , i int ) {
2023-07-21 10:55:03 +02:00
tuple := tupleType ( "T" ) ( i )
2023-07-14 17:30:58 +02:00
fmt . Fprintf ( f , "SequenceT%d[" , i )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "T%d" , j + 1 )
}
fmt . Fprintf ( f , "](" )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "t%d %s" , j + 1 , hkt ( fmt . Sprintf ( "T%d" , j + 1 ) ) )
}
fmt . Fprintf ( f , ") %s {" , hkt ( tuple ) )
// the actual apply callback
2023-07-14 23:52:14 +02:00
fmt . Fprintf ( f , " return apply.SequenceT%d(\n" , i )
2023-07-14 17:30:58 +02:00
// map callback
curried := func ( count int ) string {
var buf strings . Builder
for j := count ; j < i ; j ++ {
buf . WriteString ( fmt . Sprintf ( "func(T%d)" , j + 1 ) )
}
buf . WriteString ( tuple )
return buf . String ( )
}
fmt . Fprintf ( f , " %s,\n" , fmap ( "T1" , curried ( 1 ) ) )
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " %s,\n" , fap ( curried ( j + 1 ) , fmt . Sprintf ( "T%d" , j ) ) )
}
for j := 0 ; j < i ; j ++ {
fmt . Fprintf ( f , " T%d,\n" , j + 1 )
}
fmt . Fprintf ( f , " )\n" )
fmt . Fprintf ( f , "}\n" )
}
}
func monadGenerateSequenceTGeneric (
hkt func ( string ) string ,
fmap func ( string , string ) string ,
fap func ( string , string ) string ,
) func ( f * os . File , i int ) {
return func ( f * os . File , i int ) {
2023-07-21 10:55:03 +02:00
tuple := tupleType ( "T" ) ( i )
2023-07-14 17:30:58 +02:00
fmt . Fprintf ( f , "SequenceT%d[" , i )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "T%d" , j + 1 )
}
fmt . Fprintf ( f , "](" )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "t%d %s" , j + 1 , hkt ( fmt . Sprintf ( "T%d" , j + 1 ) ) )
}
fmt . Fprintf ( f , ") %s {" , hkt ( tuple ) )
// the actual apply callback
2023-07-14 23:52:14 +02:00
fmt . Fprintf ( f , " return apply.SequenceT%d(\n" , i )
2023-07-14 17:30:58 +02:00
// map callback
curried := func ( count int ) string {
var buf strings . Builder
for j := count ; j < i ; j ++ {
buf . WriteString ( fmt . Sprintf ( "func(T%d)" , j + 1 ) )
}
buf . WriteString ( tuple )
return buf . String ( )
}
fmt . Fprintf ( f , " %s,\n" , fmap ( "T1" , curried ( 1 ) ) )
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " %s,\n" , fap ( curried ( j + 1 ) , fmt . Sprintf ( "T%d" , j ) ) )
}
for j := 0 ; j < i ; j ++ {
fmt . Fprintf ( f , " T%d,\n" , j + 1 )
}
fmt . Fprintf ( f , " )\n" )
fmt . Fprintf ( f , "}\n" )
}
}
2023-07-17 13:55:35 +02:00
func generateTraverseTuple1 (
hkt func ( string ) string ,
infix string ) func ( f * os . File , i int ) {
return func ( f * os . File , i int ) {
2023-07-21 10:55:03 +02:00
tuple := tupleType ( "T" ) ( i )
2023-07-17 13:55:35 +02:00
fmt . Fprintf ( f , "\n// TraverseTuple%d converts a [Tuple%d] of [A] via transformation functions transforming [A] to [%s] into a [%s].\n" , i , i , hkt ( "A" ) , hkt ( fmt . Sprintf ( "Tuple%d" , i ) ) )
fmt . Fprintf ( f , "func TraverseTuple%d[" , i )
// functions
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "F%d ~func(A%d) %s" , j + 1 , j + 1 , hkt ( fmt . Sprintf ( "T%d" , j + 1 ) ) )
}
if infix != "" {
fmt . Fprintf ( f , ", %s" , infix )
}
// types
for j := 0 ; j < i ; j ++ {
fmt . Fprintf ( f , ", A%d, T%d" , j + 1 , j + 1 )
}
fmt . Fprintf ( f , " any](" )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "f%d F%d" , j + 1 , j + 1 )
}
fmt . Fprintf ( f , ") func (T.Tuple%d[" , i )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "A%d" , j + 1 )
}
fmt . Fprintf ( f , "]) %s {\n" , hkt ( tuple ) )
fmt . Fprintf ( f , " return func(t T.Tuple%d[" , i )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "A%d" , j + 1 )
}
fmt . Fprintf ( f , "]) %s {\n" , hkt ( tuple ) )
fmt . Fprintf ( f , " return A.TraverseTuple%d(\n" , i )
// map
fmt . Fprintf ( f , " Map[" )
if infix != "" {
fmt . Fprintf ( f , "%s, T1," , infix )
} else {
fmt . Fprintf ( f , "T1," )
}
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " func(T%d)" , j + 1 )
}
fmt . Fprintf ( f , " %s],\n" , tuple )
// applicatives
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " Ap[" )
for k := j + 1 ; k < i ; k ++ {
if k > j + 1 {
fmt . Fprintf ( f , " " )
}
fmt . Fprintf ( f , "func(T%d)" , k + 1 )
}
if j < i - 1 {
fmt . Fprintf ( f , " " )
}
fmt . Fprintf ( f , "%s" , tuple )
if infix != "" {
fmt . Fprintf ( f , ", %s" , infix )
}
fmt . Fprintf ( f , ", T%d],\n" , j + 1 )
}
for j := 0 ; j < i ; j ++ {
fmt . Fprintf ( f , " f%d,\n" , j + 1 )
}
fmt . Fprintf ( f , " t,\n" )
fmt . Fprintf ( f , " )\n" )
fmt . Fprintf ( f , " }\n" )
fmt . Fprintf ( f , "}\n" )
}
}
func generateSequenceTuple1 (
hkt func ( string ) string ,
infix string ) func ( f * os . File , i int ) {
return func ( f * os . File , i int ) {
2023-07-21 10:55:03 +02:00
tuple := tupleType ( "T" ) ( i )
2023-07-17 13:55:35 +02:00
fmt . Fprintf ( f , "\n// SequenceTuple%d converts a [Tuple%d] of [%s] into an [%s].\n" , i , i , hkt ( "T" ) , hkt ( fmt . Sprintf ( "Tuple%d" , i ) ) )
fmt . Fprintf ( f , "func SequenceTuple%d[" , i )
if infix != "" {
fmt . Fprintf ( f , "%s" , infix )
}
for j := 0 ; j < i ; j ++ {
if infix != "" || j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "T%d" , j + 1 )
}
fmt . Fprintf ( f , " any](t T.Tuple%d[" , i )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "%s" , hkt ( fmt . Sprintf ( "T%d" , j + 1 ) ) )
}
fmt . Fprintf ( f , "]) %s {\n" , hkt ( tuple ) )
fmt . Fprintf ( f , " return A.SequenceTuple%d(\n" , i )
// map
fmt . Fprintf ( f , " Map[" )
if infix != "" {
fmt . Fprintf ( f , "%s, T1," , infix )
} else {
fmt . Fprintf ( f , "T1," )
}
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " func(T%d)" , j + 1 )
}
fmt . Fprintf ( f , " %s],\n" , tuple )
// applicatives
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " Ap[" )
for k := j + 1 ; k < i ; k ++ {
if k > j + 1 {
fmt . Fprintf ( f , " " )
}
fmt . Fprintf ( f , "func(T%d)" , k + 1 )
}
if j < i - 1 {
fmt . Fprintf ( f , " " )
}
fmt . Fprintf ( f , "%s" , tuple )
if infix != "" {
fmt . Fprintf ( f , ", %s" , infix )
}
fmt . Fprintf ( f , ", T%d],\n" , j + 1 )
}
fmt . Fprintf ( f , " t,\n" )
fmt . Fprintf ( f , " )\n" )
fmt . Fprintf ( f , "}\n" )
}
}
2023-07-17 18:03:21 +02:00
func generateSequenceT1 (
hkt func ( string ) string ,
infix string ) func ( f * os . File , i int ) {
return func ( f * os . File , i int ) {
2023-07-21 10:55:03 +02:00
tuple := tupleType ( "T" ) ( i )
2023-07-17 18:03:21 +02:00
fmt . Fprintf ( f , "\n// SequenceT%d converts %d parameters of [%s] into a [%s].\n" , i , i , hkt ( "T" ) , hkt ( fmt . Sprintf ( "Tuple%d" , i ) ) )
fmt . Fprintf ( f , "func SequenceT%d[" , i )
if infix != "" {
fmt . Fprintf ( f , "%s" , infix )
}
for j := 0 ; j < i ; j ++ {
if infix != "" || j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "T%d" , j + 1 )
}
fmt . Fprintf ( f , " any](" )
for j := 0 ; j < i ; j ++ {
if j > 0 {
fmt . Fprintf ( f , ", " )
}
fmt . Fprintf ( f , "t%d %s" , j + 1 , hkt ( fmt . Sprintf ( "T%d" , j + 1 ) ) )
}
fmt . Fprintf ( f , ") %s {\n" , hkt ( tuple ) )
fmt . Fprintf ( f , " return A.SequenceT%d(\n" , i )
// map
fmt . Fprintf ( f , " Map[" )
if infix != "" {
fmt . Fprintf ( f , "%s, T1," , infix )
} else {
fmt . Fprintf ( f , "T1," )
}
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " func(T%d)" , j + 1 )
}
fmt . Fprintf ( f , " %s],\n" , tuple )
// applicatives
for j := 1 ; j < i ; j ++ {
fmt . Fprintf ( f , " Ap[" )
for k := j + 1 ; k < i ; k ++ {
if k > j + 1 {
fmt . Fprintf ( f , " " )
}
fmt . Fprintf ( f , "func(T%d)" , k + 1 )
}
if j < i - 1 {
fmt . Fprintf ( f , " " )
}
fmt . Fprintf ( f , "%s" , tuple )
if infix != "" {
fmt . Fprintf ( f , ", %s" , infix )
}
fmt . Fprintf ( f , ", T%d],\n" , j + 1 )
}
for j := 0 ; j < i ; j ++ {
fmt . Fprintf ( f , " t%d,\n" , j + 1 )
}
fmt . Fprintf ( f , " )\n" )
fmt . Fprintf ( f , "}\n" )
}
}