Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7545227
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 30, 20262026-05-30T08:52:26+00:00 2026-05-30T08:52:26+00:00

All right. The problem here is pretty abstract. Bear with me. I have a

  • 0

All right. The problem here is pretty abstract. Bear with me.

I have a bunch of “Units”, that each have certain properties. These properties are defined in the Seq class, like this:

class Seq a x y where
    break :: x -> (a, y)
    build :: a -> y -> x

Conceptually, the a type is the important type, x is the context used to generate an a, and y is the context used to generate any further Seq instances. break breaks the Seq down, build allows you to reconstruct it.

On individual Seq instances, this works fine. However, I also have a data constructor that looks like this:

data a :/: b = a :/: b deriving (Eq, Ord)
infixr :/:

The goal of this whole operation is to be able to compose Seq instances.

For example, if I have a, b, and c all instances of Seq such that a‘s context feeds into b and b‘s feeds into c, then I should automatically have a Seq instance for a :/: b :/: c. The class to set this up is fairly simple through the recursive data type:

instance (Seq a x y, Seq b y z) => Seq (a :/: b) x z where
    break x = let
        (a, y) = break x :: (a, y)
        (b, z) = break y :: (b, z)
        in (a :/: b, z)

    build (a :/: b) z = let
        y = build b z :: y
        x = build a y :: x
        in x

The problem is that I can’t seem to use it. If I define the following three Seq instances:

data Foo
instance Seq Foo Integer Bool

data Bar
instance Seq Bar Bool Bar

data Baz
instance Seq Baz Bar ()

(implementation details redacted, see here for more)

and a well-typed break function:

myBreak :: Integer -> (Foo :/: Bar :/: Baz)
myBreak = fst . break' where
    break' = break :: Integer -> (Foo :/: Bar :/: Baz, ())

then I can’t even compile:

No instances for (Seq Foo Integer y, Seq Bar y y1, Seq Baz y1 ())
  arising from a use of `break'
Possible fix:
  add instance declarations for
  (Seq Foo Integer y, Seq Bar y y1, Seq Baz y1 ())
In the expression: break :: Integer -> (Foo :/: (Bar :/: Baz), ())
In an equation for break':
    break' = break :: Integer -> (Foo :/: (Bar :/: Baz), ())
In an equation for `myBreak':
    myBreak
      = fst . break'
      where
          break' = break :: Integer -> (Foo :/: (Bar :/: Baz), ())

It looks to me like myBreak can’t be sure that there’s a “working thread” of contexts from Foo → Bar → Baz. How can I convince the compiler that this is well-typed?

This is one of my first excursions into type programming, so I’m undoubtedly breaking some well-established rules. I’m quite curious as to what I’m doing wrong here, but I’m also open to suggestions as to how better achieve my goals.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-30T08:52:27+00:00Added an answer on May 30, 2026 at 8:52 am

    You will probably need another language extension or two to make this work. The general problem is that multi-parameter type classes need to encode the open world assumption so, suppose someone came along and added

    instance Seq Bar Integer Float
    
    instance Seq Baz Float ()
    

    the compiler would have no way of knowing which set of instances to use. This could potentially cause undefined behavior. If the compiler just “figured out” that no other instances were available so you must have meant these then you would be in the awkward situation of having code that could break because somebody added an instance.

    The solution is to use some kind of type level function. So, if a is the important type, then perhaps there is just one combination of x and y that goes with that a. One way of doing this is with functional dependencies.

    class Seq a x y | a -> x, a -> y where
       break :: x -> (a, y)
       build :: a -> y -> x
    

    Functional dependencies are quite general, and can be used two encode bijective type functions

    class Seq a x y | a -> x, a -> y, x y -> a where
       break :: x -> (a, y)
       build :: a -> y -> x
    

    It depends on what exactly the semantics you want are. Alternatively, you can use the slightly more elegant “associated type synonym” approach using the type families extension.

    class Seq a where
       type X a
       type Y a
       break :: X a -> (a, Y a)
       build :: a -> Y a -> X a
    
    instance Seq Bar where
       type X Bar = Bool 
       type Y Bar = Bar
    

    This version is currently considered the most idiomatic, and has some advantages over the functional dependancies version (although, you cant encode bijection this way). For completeness, this is equivalent to

    type family X a
    type instance X Bar = Bool
    
    type family Y a
    type instance Y Bar = Bar
    
    class Seq a where
       break :: X a -> (a, Y a)
       build :: a -> Y a -> X a
    
    instance Seq Bar
    

    To editorialize: Haskell constraint solving mechanism with multi parameter type classes is a logic language kinda like prolog. As much as possible you should use functions instead of relations when type level programming. Three reasons:

    1. You can get from a function to a constraint but not vice versa
    2. Haskell is not prolog. Most Haskell programmers find functions easier to reason about. If you dont know Prolog (or another logic language), its extra important to stick to functions since the difference between relational and functional programming is almost as big as the difference between functional and imperative programming.
    3. Despite similarities, Haskell’s constraint solver is NOT Prolog (intuitively all clauses have a cut immediately after the head, dont worry if you dont know what this means). Relational type programming is much harder than coding in a language with full backtracking.

    My recommendation is know both functional dependencies and type functions. Type functions fit in a little better with the rest of the language, but sometimes functional dependencies are the best tool for the job.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a pretty simple problem, but right now can't seem to see the
Ok here is the problem in brief. I do have a pyramid setup that
All right all, So I've got a UITableView that is inited in applicationDidFinishLaunching like
The WebBrowser control has a property called IsWebBrowserContextMenuEnabled that disables all ability to right-click
I have a pretty basic slideshow fading between images. On top of that slideshow
Search as I may I have not found a solution to my problem here
I don't understand this at all. Here is some Javascript code that works in
For a problem that I'm working on right now, I would like a reasonably
I'm using the OnIdle-event for some simple animations, and it works all right. The
you all know: right click -> zoom in or out in flash file, well,

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.