Code Monkey home page Code Monkey logo

Comments (2)

dillonkearns avatar dillonkearns commented on June 26, 2024

Hey @Hazelfire, thanks for the discussion. I see what you're saying there, that's an interesting point.

I think you're right that the selectFromCourse type signature would be one way to support that.

Another idea, though a much more drastic change, would be to use Records as the Phantom Types. So taking this example from the Star Wars API example, since I'm looking at this source code in the examples folder for this one:

{-| The name of the human.
-}
name : SelectionSet String Swapi.Object.Human
name =
Object.selectionForField "String" "name" [] Decode.string

{-| The name of the character.
-}
name : SelectionSet String Swapi.Interface.Character
name =
Object.selectionForField "String" "name" [] Decode.string

hero :
(HeroOptionalArguments -> HeroOptionalArguments)
-> SelectionSet decodesTo Swapi.Interface.Character
-> SelectionSet decodesTo RootQuery
hero fillInOptionals____ object____ =
let
filledInOptionals____ =
fillInOptionals____ { episode = Absent }
optionalArgs____ =
[ Argument.optional "episode" filledInOptionals____.episode (Encode.enum Swapi.Enum.Episode.toString) ]
|> List.filterMap Basics.identity
in
Object.selectionForCompositeField "hero" optionalArgs____ object____ Basics.identity

What if it was something like this:

-- in Swapi.Interface.Character
name : SelectionSet String { objectHuman : () }
name =
    Object.selectionForField "String" "name" [] Decode.string
-- in Swapi.Interface.Character
name : SelectionSet String { interfaceCharacter : (), objectHuman : (), objectDroid : () }
name =
    Object.selectionForField "String" "name" [] Decode.string
hero :
    (HeroOptionalArguments -> HeroOptionalArguments)
    -> SelectionSet decodesTo { character | interfaceCharacter : () }
    -> SelectionSet decodesTo RootQuery

This would allow you to have

Benefits of Record Approach

This is lightweight in a few ways.

  1. You can intermix things that need the name field as part of a Character interface, or as part of one of its Object implementors (Droid or Human)
  2. No import needed for the named types (Swapi.Interface.Character, etc.) - they are just records now, so they're structurally typed rather than nominally typed

Downsides of Record Approach

  1. Is it more cumbersome or confusing to have these records rather than named types?
  2. More type variables in a few places. Could that be confusing for some users? Could that be cumbersome at all in any cases even for users who are familiar with that technique?
  3. In an API with a ton of types, this could become unwieldy. For example, the Node type in GitHub has almost 80 different implementors:
    { onAddedToProjectEvent : SelectionSet decodesTo Github.Object.AddedToProjectEvent
    , onAssignedEvent : SelectionSet decodesTo Github.Object.AssignedEvent
    , onBaseRefChangedEvent : SelectionSet decodesTo Github.Object.BaseRefChangedEvent
    , onBaseRefForcePushedEvent : SelectionSet decodesTo Github.Object.BaseRefForcePushedEvent
    , onBlob : SelectionSet decodesTo Github.Object.Blob
    , onBot : SelectionSet decodesTo Github.Object.Bot
    , onClosedEvent : SelectionSet decodesTo Github.Object.ClosedEvent
    , onCommentDeletedEvent : SelectionSet decodesTo Github.Object.CommentDeletedEvent
    , onCommit : SelectionSet decodesTo Github.Object.Commit
    , onCommitComment : SelectionSet decodesTo Github.Object.CommitComment
    , onCommitCommentThread : SelectionSet decodesTo Github.Object.CommitCommentThread
    , onConvertedNoteToIssueEvent : SelectionSet decodesTo Github.Object.ConvertedNoteToIssueEvent
    , onCrossReferencedEvent : SelectionSet decodesTo Github.Object.CrossReferencedEvent
    , onDemilestonedEvent : SelectionSet decodesTo Github.Object.DemilestonedEvent
    , onDeployKey : SelectionSet decodesTo Github.Object.DeployKey
    , onDeployedEvent : SelectionSet decodesTo Github.Object.DeployedEvent
    , onDeployment : SelectionSet decodesTo Github.Object.Deployment
    , onDeploymentStatus : SelectionSet decodesTo Github.Object.DeploymentStatus
    , onExternalIdentity : SelectionSet decodesTo Github.Object.ExternalIdentity
    , onGist : SelectionSet decodesTo Github.Object.Gist
    , onGistComment : SelectionSet decodesTo Github.Object.GistComment
    , onHeadRefDeletedEvent : SelectionSet decodesTo Github.Object.HeadRefDeletedEvent
    , onHeadRefForcePushedEvent : SelectionSet decodesTo Github.Object.HeadRefForcePushedEvent
    , onHeadRefRestoredEvent : SelectionSet decodesTo Github.Object.HeadRefRestoredEvent
    , onIssue : SelectionSet decodesTo Github.Object.Issue
    , onIssueComment : SelectionSet decodesTo Github.Object.IssueComment
    , onLabel : SelectionSet decodesTo Github.Object.Label
    , onLabeledEvent : SelectionSet decodesTo Github.Object.LabeledEvent
    , onLanguage : SelectionSet decodesTo Github.Object.Language
    , onLockedEvent : SelectionSet decodesTo Github.Object.LockedEvent
    , onMarketplaceListing : SelectionSet decodesTo Github.Object.MarketplaceListing
    , onMentionedEvent : SelectionSet decodesTo Github.Object.MentionedEvent
    , onMergedEvent : SelectionSet decodesTo Github.Object.MergedEvent
    , onMilestone : SelectionSet decodesTo Github.Object.Milestone
    , onMilestonedEvent : SelectionSet decodesTo Github.Object.MilestonedEvent
    , onMovedColumnsInProjectEvent : SelectionSet decodesTo Github.Object.MovedColumnsInProjectEvent
    , onOrganization : SelectionSet decodesTo Github.Object.Organization
    , onOrganizationIdentityProvider : SelectionSet decodesTo Github.Object.OrganizationIdentityProvider
    , onOrganizationInvitation : SelectionSet decodesTo Github.Object.OrganizationInvitation
    , onProject : SelectionSet decodesTo Github.Object.Project
    , onProjectCard : SelectionSet decodesTo Github.Object.ProjectCard
    , onProjectColumn : SelectionSet decodesTo Github.Object.ProjectColumn
    , onProtectedBranch : SelectionSet decodesTo Github.Object.ProtectedBranch
    , onPublicKey : SelectionSet decodesTo Github.Object.PublicKey
    , onPullRequest : SelectionSet decodesTo Github.Object.PullRequest
    , onPullRequestCommit : SelectionSet decodesTo Github.Object.PullRequestCommit
    , onPullRequestReview : SelectionSet decodesTo Github.Object.PullRequestReview
    , onPullRequestReviewComment : SelectionSet decodesTo Github.Object.PullRequestReviewComment
    , onPullRequestReviewThread : SelectionSet decodesTo Github.Object.PullRequestReviewThread
    , onPushAllowance : SelectionSet decodesTo Github.Object.PushAllowance
    , onReaction : SelectionSet decodesTo Github.Object.Reaction
    , onRef : SelectionSet decodesTo Github.Object.Ref
    , onReferencedEvent : SelectionSet decodesTo Github.Object.ReferencedEvent
    , onRelease : SelectionSet decodesTo Github.Object.Release
    , onReleaseAsset : SelectionSet decodesTo Github.Object.ReleaseAsset
    , onRemovedFromProjectEvent : SelectionSet decodesTo Github.Object.RemovedFromProjectEvent
    , onRenamedTitleEvent : SelectionSet decodesTo Github.Object.RenamedTitleEvent
    , onReopenedEvent : SelectionSet decodesTo Github.Object.ReopenedEvent
    , onRepository : SelectionSet decodesTo Github.Object.Repository
    , onRepositoryInvitation : SelectionSet decodesTo Github.Object.RepositoryInvitation
    , onRepositoryTopic : SelectionSet decodesTo Github.Object.RepositoryTopic
    , onReviewDismissalAllowance : SelectionSet decodesTo Github.Object.ReviewDismissalAllowance
    , onReviewDismissedEvent : SelectionSet decodesTo Github.Object.ReviewDismissedEvent
    , onReviewRequest : SelectionSet decodesTo Github.Object.ReviewRequest
    , onReviewRequestRemovedEvent : SelectionSet decodesTo Github.Object.ReviewRequestRemovedEvent
    , onReviewRequestedEvent : SelectionSet decodesTo Github.Object.ReviewRequestedEvent
    , onStatus : SelectionSet decodesTo Github.Object.Status
    , onStatusContext : SelectionSet decodesTo Github.Object.StatusContext
    , onSubscribedEvent : SelectionSet decodesTo Github.Object.SubscribedEvent
    , onTag : SelectionSet decodesTo Github.Object.Tag
    , onTeam : SelectionSet decodesTo Github.Object.Team
    , onTopic : SelectionSet decodesTo Github.Object.Topic
    , onTree : SelectionSet decodesTo Github.Object.Tree
    , onUnassignedEvent : SelectionSet decodesTo Github.Object.UnassignedEvent
    , onUnlabeledEvent : SelectionSet decodesTo Github.Object.UnlabeledEvent
    , onUnlockedEvent : SelectionSet decodesTo Github.Object.UnlockedEvent
    , onUnsubscribedEvent : SelectionSet decodesTo Github.Object.UnsubscribedEvent
    , onUser : SelectionSet decodesTo Github.Object.User
    , onUserContentEdit : SelectionSet decodesTo Github.Object.UserContentEdit
    }
    - these could be given type aliases easily, so maybe that would be fine?

Thoughts

Anyway, just throwing an idea out there, still need to think on it a little to decide if it's good or not. But seems like it might be worth considering that direction more seriously.

from elm-graphql.

Hazelfire avatar Hazelfire commented on June 26, 2024

I've come back to this several times, trying to understand what you mean and how it could be implemented.
The fact that I still don't understand it is a bit of a concern.

I think I get the general idea, but I do think that it might be a bit too on the nose of what's possible, and a much simpler implementation with much more obvious ways to do this might be preferable, at least in my eyes.

from elm-graphql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.