PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, October 28, 2022

[FIXED] How can I demonstrate that a function space is not empty?

 October 28, 2022     haskell, is-empty     No comments   

Issue

I declared a class of types that admits a value:

class NonEmpty a where
    example :: a

And also, I declared the complement class:

import Data.Void

class Empty a where
    exampleless :: a -> Void

Demonstrating a function space is empty is easy:

instance (NonEmpty a, Empty b) => Empty (a -> b) where
    exampleless f = exampleless (f example)

But what about its complement? Haskell doesn't let me have these instances simultaneously:

instance Empty a => NonEmpty (a -> b) where
    example = absurd . exampleless

instance NonEmpty b => NonEmpty (a -> b) where
    example _ = example

Is there any way to bypass this problem?


Solution

You can merge the two classes together into one that expresses decidability of whether or not the type is inhabited:

{-# LANGUAGE TypeFamilies, DataKinds
      , KindSignatures, TypeApplications, UndecidableInstances
      , ScopedTypeVariables, UnicodeSyntax #-}

import Data.Kind (Type)
import Data.Type.Bool
import Data.Void

data Inhabitedness :: Bool -> Type -> Type where
  IsEmpty :: (a -> Void) -> Inhabitedness 'False a
  IsInhabited :: a -> Inhabitedness 'True a

class KnownInhabitedness a where
  type IsInhabited a :: Bool
  inhabitedness :: Inhabitedness (IsInhabited a) a

instance ∀ a b . (KnownInhabitedness a, KnownInhabitedness b)
              => KnownInhabitedness (a -> b) where
  type IsInhabited (a -> b) = Not (IsInhabited a) || IsInhabited b
  inhabitedness = case (inhabitedness @a, inhabitedness @b) of
    (IsEmpty no_a, _) -> IsInhabited $ absurd . no_a
    (_, IsInhabited b) -> IsInhabited $ const b
    (IsInhabited a, IsEmpty no_b) -> IsEmpty $ \f -> no_b $ f a

To get again your simpler interface, use

{-# LANGUAGE ConstraintKinds #-}

type Empty a = (KnownInhabitedness a, IsInhabited a ~ 'False)
type NonEmpty a = (KnownInhabitedness a, IsInhabited a ~ 'True)

exampleless :: ∀ a . Empty a => a -> Void
exampleless = case inhabitedness @a of
   IsEmpty no_a -> no_a

example :: ∀ a . NonEmpty a => a
example = case inhabitedness @a of
   IsInhabited a -> a


Answered By - leftaroundabout
Answer Checked By - Marie Seifert (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing