Liquid Haskell: “Cyclic type alias definition” error from an inlined recursive function












4















I wrote some code to do ordinal arithmetic in Haskell and am now trying to use Liquid Haskell to verify certain properties. However, I'm having trouble "reflecting" recursive functions. I've isolated a problem in the "less than" function below:



-- (Ord a n b) = a^n + b
{-@ data Ordinal [size] = Ord { a :: Ordinal, n :: Nat, b :: Ordinal }
| Zero {} @-}
data Ordinal = Ord Ordinal Integer Ordinal
| Zero
deriving (Eq, Show)

{-@ measure size @-}
{-@ size :: Ordinal -> Nat @-}
size :: Ordinal -> Integer
size Zero = 1
size (Ord a n b) = (size a) + 1 + (size b)

{-@ inline ordLT @-}
ordLT :: Ordinal -> Ordinal -> Bool
ordLT _ Zero = False
ordLT Zero _ = True
ordLT (Ord a0 n0 b0) (Ord a1 n1 b1) =
(ordLT a0 a1) ||
(a0 == a1 && n0 < n1) ||
(a0 == a1 && n0 == n1 && ordLT b0 b1)

one = (Ord Zero 1 Zero) -- 1
w = (Ord one 1 Zero) -- omega
main = print w -- Ord (Ord Zero 1 Zero) 1 Zero


Executing liquid ordinals.hs with just the above gives the following error:



Error: Cyclic type alias definition for `Main.ordLT`
14 | {-@ inline ordLT @-}
^^^^^
The following alias definitions form a cycle:
* `Main.ordLT`


So what is the proper way to reflect recursive functions? I've read the liquid haskell tutorial but I can't figure out what its examples are doing differently.










share|improve this question


















  • 3





    I guess you can't inline recursive functions. How would that work?

    – chi
    Nov 21 '18 at 19:35











  • I guess I'm not exactly sure what "inline" (or the other pragmas) do. Maybe there is a different one I should be using?

    – Alex Varga
    Nov 21 '18 at 21:07






  • 2





    The README seems to document this, suggests you might need to use reflect , but I'm afraid I haven't used LH much yet github.com/ucsd-progsys/liquidhaskell/blob/develop/README.md

    – jberryman
    Nov 21 '18 at 21:52











  • This is the best resource I've found on this: arxiv.org/pdf/1806.03541.pdf. Just make sure to use NewProofCombinators rather than ProofCombinators.

    – Alex Varga
    Nov 30 '18 at 17:40


















4















I wrote some code to do ordinal arithmetic in Haskell and am now trying to use Liquid Haskell to verify certain properties. However, I'm having trouble "reflecting" recursive functions. I've isolated a problem in the "less than" function below:



-- (Ord a n b) = a^n + b
{-@ data Ordinal [size] = Ord { a :: Ordinal, n :: Nat, b :: Ordinal }
| Zero {} @-}
data Ordinal = Ord Ordinal Integer Ordinal
| Zero
deriving (Eq, Show)

{-@ measure size @-}
{-@ size :: Ordinal -> Nat @-}
size :: Ordinal -> Integer
size Zero = 1
size (Ord a n b) = (size a) + 1 + (size b)

{-@ inline ordLT @-}
ordLT :: Ordinal -> Ordinal -> Bool
ordLT _ Zero = False
ordLT Zero _ = True
ordLT (Ord a0 n0 b0) (Ord a1 n1 b1) =
(ordLT a0 a1) ||
(a0 == a1 && n0 < n1) ||
(a0 == a1 && n0 == n1 && ordLT b0 b1)

one = (Ord Zero 1 Zero) -- 1
w = (Ord one 1 Zero) -- omega
main = print w -- Ord (Ord Zero 1 Zero) 1 Zero


Executing liquid ordinals.hs with just the above gives the following error:



Error: Cyclic type alias definition for `Main.ordLT`
14 | {-@ inline ordLT @-}
^^^^^
The following alias definitions form a cycle:
* `Main.ordLT`


So what is the proper way to reflect recursive functions? I've read the liquid haskell tutorial but I can't figure out what its examples are doing differently.










share|improve this question


















  • 3





    I guess you can't inline recursive functions. How would that work?

    – chi
    Nov 21 '18 at 19:35











  • I guess I'm not exactly sure what "inline" (or the other pragmas) do. Maybe there is a different one I should be using?

    – Alex Varga
    Nov 21 '18 at 21:07






  • 2





    The README seems to document this, suggests you might need to use reflect , but I'm afraid I haven't used LH much yet github.com/ucsd-progsys/liquidhaskell/blob/develop/README.md

    – jberryman
    Nov 21 '18 at 21:52











  • This is the best resource I've found on this: arxiv.org/pdf/1806.03541.pdf. Just make sure to use NewProofCombinators rather than ProofCombinators.

    – Alex Varga
    Nov 30 '18 at 17:40
















4












4








4


2






I wrote some code to do ordinal arithmetic in Haskell and am now trying to use Liquid Haskell to verify certain properties. However, I'm having trouble "reflecting" recursive functions. I've isolated a problem in the "less than" function below:



-- (Ord a n b) = a^n + b
{-@ data Ordinal [size] = Ord { a :: Ordinal, n :: Nat, b :: Ordinal }
| Zero {} @-}
data Ordinal = Ord Ordinal Integer Ordinal
| Zero
deriving (Eq, Show)

{-@ measure size @-}
{-@ size :: Ordinal -> Nat @-}
size :: Ordinal -> Integer
size Zero = 1
size (Ord a n b) = (size a) + 1 + (size b)

{-@ inline ordLT @-}
ordLT :: Ordinal -> Ordinal -> Bool
ordLT _ Zero = False
ordLT Zero _ = True
ordLT (Ord a0 n0 b0) (Ord a1 n1 b1) =
(ordLT a0 a1) ||
(a0 == a1 && n0 < n1) ||
(a0 == a1 && n0 == n1 && ordLT b0 b1)

one = (Ord Zero 1 Zero) -- 1
w = (Ord one 1 Zero) -- omega
main = print w -- Ord (Ord Zero 1 Zero) 1 Zero


Executing liquid ordinals.hs with just the above gives the following error:



Error: Cyclic type alias definition for `Main.ordLT`
14 | {-@ inline ordLT @-}
^^^^^
The following alias definitions form a cycle:
* `Main.ordLT`


So what is the proper way to reflect recursive functions? I've read the liquid haskell tutorial but I can't figure out what its examples are doing differently.










share|improve this question














I wrote some code to do ordinal arithmetic in Haskell and am now trying to use Liquid Haskell to verify certain properties. However, I'm having trouble "reflecting" recursive functions. I've isolated a problem in the "less than" function below:



-- (Ord a n b) = a^n + b
{-@ data Ordinal [size] = Ord { a :: Ordinal, n :: Nat, b :: Ordinal }
| Zero {} @-}
data Ordinal = Ord Ordinal Integer Ordinal
| Zero
deriving (Eq, Show)

{-@ measure size @-}
{-@ size :: Ordinal -> Nat @-}
size :: Ordinal -> Integer
size Zero = 1
size (Ord a n b) = (size a) + 1 + (size b)

{-@ inline ordLT @-}
ordLT :: Ordinal -> Ordinal -> Bool
ordLT _ Zero = False
ordLT Zero _ = True
ordLT (Ord a0 n0 b0) (Ord a1 n1 b1) =
(ordLT a0 a1) ||
(a0 == a1 && n0 < n1) ||
(a0 == a1 && n0 == n1 && ordLT b0 b1)

one = (Ord Zero 1 Zero) -- 1
w = (Ord one 1 Zero) -- omega
main = print w -- Ord (Ord Zero 1 Zero) 1 Zero


Executing liquid ordinals.hs with just the above gives the following error:



Error: Cyclic type alias definition for `Main.ordLT`
14 | {-@ inline ordLT @-}
^^^^^
The following alias definitions form a cycle:
* `Main.ordLT`


So what is the proper way to reflect recursive functions? I've read the liquid haskell tutorial but I can't figure out what its examples are doing differently.







haskell refinement-type liquid-haskell






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 21 '18 at 19:06









Alex VargaAlex Varga

1,38311117




1,38311117








  • 3





    I guess you can't inline recursive functions. How would that work?

    – chi
    Nov 21 '18 at 19:35











  • I guess I'm not exactly sure what "inline" (or the other pragmas) do. Maybe there is a different one I should be using?

    – Alex Varga
    Nov 21 '18 at 21:07






  • 2





    The README seems to document this, suggests you might need to use reflect , but I'm afraid I haven't used LH much yet github.com/ucsd-progsys/liquidhaskell/blob/develop/README.md

    – jberryman
    Nov 21 '18 at 21:52











  • This is the best resource I've found on this: arxiv.org/pdf/1806.03541.pdf. Just make sure to use NewProofCombinators rather than ProofCombinators.

    – Alex Varga
    Nov 30 '18 at 17:40
















  • 3





    I guess you can't inline recursive functions. How would that work?

    – chi
    Nov 21 '18 at 19:35











  • I guess I'm not exactly sure what "inline" (or the other pragmas) do. Maybe there is a different one I should be using?

    – Alex Varga
    Nov 21 '18 at 21:07






  • 2





    The README seems to document this, suggests you might need to use reflect , but I'm afraid I haven't used LH much yet github.com/ucsd-progsys/liquidhaskell/blob/develop/README.md

    – jberryman
    Nov 21 '18 at 21:52











  • This is the best resource I've found on this: arxiv.org/pdf/1806.03541.pdf. Just make sure to use NewProofCombinators rather than ProofCombinators.

    – Alex Varga
    Nov 30 '18 at 17:40










3




3





I guess you can't inline recursive functions. How would that work?

– chi
Nov 21 '18 at 19:35





I guess you can't inline recursive functions. How would that work?

– chi
Nov 21 '18 at 19:35













I guess I'm not exactly sure what "inline" (or the other pragmas) do. Maybe there is a different one I should be using?

– Alex Varga
Nov 21 '18 at 21:07





I guess I'm not exactly sure what "inline" (or the other pragmas) do. Maybe there is a different one I should be using?

– Alex Varga
Nov 21 '18 at 21:07




2




2





The README seems to document this, suggests you might need to use reflect , but I'm afraid I haven't used LH much yet github.com/ucsd-progsys/liquidhaskell/blob/develop/README.md

– jberryman
Nov 21 '18 at 21:52





The README seems to document this, suggests you might need to use reflect , but I'm afraid I haven't used LH much yet github.com/ucsd-progsys/liquidhaskell/blob/develop/README.md

– jberryman
Nov 21 '18 at 21:52













This is the best resource I've found on this: arxiv.org/pdf/1806.03541.pdf. Just make sure to use NewProofCombinators rather than ProofCombinators.

– Alex Varga
Nov 30 '18 at 17:40







This is the best resource I've found on this: arxiv.org/pdf/1806.03541.pdf. Just make sure to use NewProofCombinators rather than ProofCombinators.

– Alex Varga
Nov 30 '18 at 17:40














1 Answer
1






active

oldest

votes


















2














It's a little difficult to be sure what you want to be doing without more context, but inline does indeed not work on recursive functions: inline lets you use a function in a type by expanding it at compile time (before creating the verification condition sent to the solver), so it needs to be possible to replace every occurrence of ordLT a b by some specific logic formula (which is impossible, since it's recursive).



If you need to be able to use arbitrary Haskell functions in the logic, you can look into using Refinement Reflection. Your example compiles with {-@ reflect ordLT @-} and {-@ LIQUID "--exact-data-cons" @-}. However, the function symbols created by refinement reflection are not automatically fully interpreted in the logic. The nitty-gritty details are discussed in this paper, and more approachable examples/explanation are present in these slides and this blog post. The main point to remember is that the ordLT symbol created by reflection will initially be treated as a completely uninterpreted function in the logic: the only thing that LH knows about it is something like a0 == a1 ==> b0 == b1 ==> ordLT a0 b0 == ordLT a1 b1 (if you call it on identical inputs, the results are identical).



In order to do something useful with ordLT in the logic, you will need to call ordLT at the value-level somewhere in scope, which will reveal the value of that particular call, since the return type of ordLT (the value-level function) asserts something about the output of ordLT (the logic-level uninterpreted function) on those inputs. Examples are given in the slides linked above & the paper. I hope that's enough to get you started!






share|improve this answer
























  • Thanks for you thorough answer Peter! I had figured out the need to use reflect but was still struggling to get LH to "understand" the function, and I believe those resources will help.

    – Alex Varga
    Nov 23 '18 at 11:22











  • Follow up: if I declare type LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }, how can I actually declare something like one :: LT5 without an error? Even if I prove ordLT one (Ord Zero 5 Zero), LH still doesn't allow this.

    – Alex Varga
    Nov 23 '18 at 19:07






  • 1





    @AlexVarga You need to ensure that the proof of this fact is in scope when Liquid is typechecking the definition. You might want to look at some of the combinators in the Language.Haskell.Liquid.ProofCombinators module, which are designed for dealing with this kind of thing. e.g. something like one = let one' = Ord Zero 1 Zero in castWithTheorem (ordLT one' $ Ord Zero 5 Zero) one' should work in this case.

    – Peter Amidon
    Nov 23 '18 at 21:13











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53418969%2fliquid-haskell-cyclic-type-alias-definition-error-from-an-inlined-recursive-f%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














It's a little difficult to be sure what you want to be doing without more context, but inline does indeed not work on recursive functions: inline lets you use a function in a type by expanding it at compile time (before creating the verification condition sent to the solver), so it needs to be possible to replace every occurrence of ordLT a b by some specific logic formula (which is impossible, since it's recursive).



If you need to be able to use arbitrary Haskell functions in the logic, you can look into using Refinement Reflection. Your example compiles with {-@ reflect ordLT @-} and {-@ LIQUID "--exact-data-cons" @-}. However, the function symbols created by refinement reflection are not automatically fully interpreted in the logic. The nitty-gritty details are discussed in this paper, and more approachable examples/explanation are present in these slides and this blog post. The main point to remember is that the ordLT symbol created by reflection will initially be treated as a completely uninterpreted function in the logic: the only thing that LH knows about it is something like a0 == a1 ==> b0 == b1 ==> ordLT a0 b0 == ordLT a1 b1 (if you call it on identical inputs, the results are identical).



In order to do something useful with ordLT in the logic, you will need to call ordLT at the value-level somewhere in scope, which will reveal the value of that particular call, since the return type of ordLT (the value-level function) asserts something about the output of ordLT (the logic-level uninterpreted function) on those inputs. Examples are given in the slides linked above & the paper. I hope that's enough to get you started!






share|improve this answer
























  • Thanks for you thorough answer Peter! I had figured out the need to use reflect but was still struggling to get LH to "understand" the function, and I believe those resources will help.

    – Alex Varga
    Nov 23 '18 at 11:22











  • Follow up: if I declare type LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }, how can I actually declare something like one :: LT5 without an error? Even if I prove ordLT one (Ord Zero 5 Zero), LH still doesn't allow this.

    – Alex Varga
    Nov 23 '18 at 19:07






  • 1





    @AlexVarga You need to ensure that the proof of this fact is in scope when Liquid is typechecking the definition. You might want to look at some of the combinators in the Language.Haskell.Liquid.ProofCombinators module, which are designed for dealing with this kind of thing. e.g. something like one = let one' = Ord Zero 1 Zero in castWithTheorem (ordLT one' $ Ord Zero 5 Zero) one' should work in this case.

    – Peter Amidon
    Nov 23 '18 at 21:13
















2














It's a little difficult to be sure what you want to be doing without more context, but inline does indeed not work on recursive functions: inline lets you use a function in a type by expanding it at compile time (before creating the verification condition sent to the solver), so it needs to be possible to replace every occurrence of ordLT a b by some specific logic formula (which is impossible, since it's recursive).



If you need to be able to use arbitrary Haskell functions in the logic, you can look into using Refinement Reflection. Your example compiles with {-@ reflect ordLT @-} and {-@ LIQUID "--exact-data-cons" @-}. However, the function symbols created by refinement reflection are not automatically fully interpreted in the logic. The nitty-gritty details are discussed in this paper, and more approachable examples/explanation are present in these slides and this blog post. The main point to remember is that the ordLT symbol created by reflection will initially be treated as a completely uninterpreted function in the logic: the only thing that LH knows about it is something like a0 == a1 ==> b0 == b1 ==> ordLT a0 b0 == ordLT a1 b1 (if you call it on identical inputs, the results are identical).



In order to do something useful with ordLT in the logic, you will need to call ordLT at the value-level somewhere in scope, which will reveal the value of that particular call, since the return type of ordLT (the value-level function) asserts something about the output of ordLT (the logic-level uninterpreted function) on those inputs. Examples are given in the slides linked above & the paper. I hope that's enough to get you started!






share|improve this answer
























  • Thanks for you thorough answer Peter! I had figured out the need to use reflect but was still struggling to get LH to "understand" the function, and I believe those resources will help.

    – Alex Varga
    Nov 23 '18 at 11:22











  • Follow up: if I declare type LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }, how can I actually declare something like one :: LT5 without an error? Even if I prove ordLT one (Ord Zero 5 Zero), LH still doesn't allow this.

    – Alex Varga
    Nov 23 '18 at 19:07






  • 1





    @AlexVarga You need to ensure that the proof of this fact is in scope when Liquid is typechecking the definition. You might want to look at some of the combinators in the Language.Haskell.Liquid.ProofCombinators module, which are designed for dealing with this kind of thing. e.g. something like one = let one' = Ord Zero 1 Zero in castWithTheorem (ordLT one' $ Ord Zero 5 Zero) one' should work in this case.

    – Peter Amidon
    Nov 23 '18 at 21:13














2












2








2







It's a little difficult to be sure what you want to be doing without more context, but inline does indeed not work on recursive functions: inline lets you use a function in a type by expanding it at compile time (before creating the verification condition sent to the solver), so it needs to be possible to replace every occurrence of ordLT a b by some specific logic formula (which is impossible, since it's recursive).



If you need to be able to use arbitrary Haskell functions in the logic, you can look into using Refinement Reflection. Your example compiles with {-@ reflect ordLT @-} and {-@ LIQUID "--exact-data-cons" @-}. However, the function symbols created by refinement reflection are not automatically fully interpreted in the logic. The nitty-gritty details are discussed in this paper, and more approachable examples/explanation are present in these slides and this blog post. The main point to remember is that the ordLT symbol created by reflection will initially be treated as a completely uninterpreted function in the logic: the only thing that LH knows about it is something like a0 == a1 ==> b0 == b1 ==> ordLT a0 b0 == ordLT a1 b1 (if you call it on identical inputs, the results are identical).



In order to do something useful with ordLT in the logic, you will need to call ordLT at the value-level somewhere in scope, which will reveal the value of that particular call, since the return type of ordLT (the value-level function) asserts something about the output of ordLT (the logic-level uninterpreted function) on those inputs. Examples are given in the slides linked above & the paper. I hope that's enough to get you started!






share|improve this answer













It's a little difficult to be sure what you want to be doing without more context, but inline does indeed not work on recursive functions: inline lets you use a function in a type by expanding it at compile time (before creating the verification condition sent to the solver), so it needs to be possible to replace every occurrence of ordLT a b by some specific logic formula (which is impossible, since it's recursive).



If you need to be able to use arbitrary Haskell functions in the logic, you can look into using Refinement Reflection. Your example compiles with {-@ reflect ordLT @-} and {-@ LIQUID "--exact-data-cons" @-}. However, the function symbols created by refinement reflection are not automatically fully interpreted in the logic. The nitty-gritty details are discussed in this paper, and more approachable examples/explanation are present in these slides and this blog post. The main point to remember is that the ordLT symbol created by reflection will initially be treated as a completely uninterpreted function in the logic: the only thing that LH knows about it is something like a0 == a1 ==> b0 == b1 ==> ordLT a0 b0 == ordLT a1 b1 (if you call it on identical inputs, the results are identical).



In order to do something useful with ordLT in the logic, you will need to call ordLT at the value-level somewhere in scope, which will reveal the value of that particular call, since the return type of ordLT (the value-level function) asserts something about the output of ordLT (the logic-level uninterpreted function) on those inputs. Examples are given in the slides linked above & the paper. I hope that's enough to get you started!







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 22 '18 at 18:49









Peter AmidonPeter Amidon

1,145311




1,145311













  • Thanks for you thorough answer Peter! I had figured out the need to use reflect but was still struggling to get LH to "understand" the function, and I believe those resources will help.

    – Alex Varga
    Nov 23 '18 at 11:22











  • Follow up: if I declare type LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }, how can I actually declare something like one :: LT5 without an error? Even if I prove ordLT one (Ord Zero 5 Zero), LH still doesn't allow this.

    – Alex Varga
    Nov 23 '18 at 19:07






  • 1





    @AlexVarga You need to ensure that the proof of this fact is in scope when Liquid is typechecking the definition. You might want to look at some of the combinators in the Language.Haskell.Liquid.ProofCombinators module, which are designed for dealing with this kind of thing. e.g. something like one = let one' = Ord Zero 1 Zero in castWithTheorem (ordLT one' $ Ord Zero 5 Zero) one' should work in this case.

    – Peter Amidon
    Nov 23 '18 at 21:13



















  • Thanks for you thorough answer Peter! I had figured out the need to use reflect but was still struggling to get LH to "understand" the function, and I believe those resources will help.

    – Alex Varga
    Nov 23 '18 at 11:22











  • Follow up: if I declare type LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }, how can I actually declare something like one :: LT5 without an error? Even if I prove ordLT one (Ord Zero 5 Zero), LH still doesn't allow this.

    – Alex Varga
    Nov 23 '18 at 19:07






  • 1





    @AlexVarga You need to ensure that the proof of this fact is in scope when Liquid is typechecking the definition. You might want to look at some of the combinators in the Language.Haskell.Liquid.ProofCombinators module, which are designed for dealing with this kind of thing. e.g. something like one = let one' = Ord Zero 1 Zero in castWithTheorem (ordLT one' $ Ord Zero 5 Zero) one' should work in this case.

    – Peter Amidon
    Nov 23 '18 at 21:13

















Thanks for you thorough answer Peter! I had figured out the need to use reflect but was still struggling to get LH to "understand" the function, and I believe those resources will help.

– Alex Varga
Nov 23 '18 at 11:22





Thanks for you thorough answer Peter! I had figured out the need to use reflect but was still struggling to get LH to "understand" the function, and I believe those resources will help.

– Alex Varga
Nov 23 '18 at 11:22













Follow up: if I declare type LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }, how can I actually declare something like one :: LT5 without an error? Even if I prove ordLT one (Ord Zero 5 Zero), LH still doesn't allow this.

– Alex Varga
Nov 23 '18 at 19:07





Follow up: if I declare type LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }, how can I actually declare something like one :: LT5 without an error? Even if I prove ordLT one (Ord Zero 5 Zero), LH still doesn't allow this.

– Alex Varga
Nov 23 '18 at 19:07




1




1





@AlexVarga You need to ensure that the proof of this fact is in scope when Liquid is typechecking the definition. You might want to look at some of the combinators in the Language.Haskell.Liquid.ProofCombinators module, which are designed for dealing with this kind of thing. e.g. something like one = let one' = Ord Zero 1 Zero in castWithTheorem (ordLT one' $ Ord Zero 5 Zero) one' should work in this case.

– Peter Amidon
Nov 23 '18 at 21:13





@AlexVarga You need to ensure that the proof of this fact is in scope when Liquid is typechecking the definition. You might want to look at some of the combinators in the Language.Haskell.Liquid.ProofCombinators module, which are designed for dealing with this kind of thing. e.g. something like one = let one' = Ord Zero 1 Zero in castWithTheorem (ordLT one' $ Ord Zero 5 Zero) one' should work in this case.

– Peter Amidon
Nov 23 '18 at 21:13


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53418969%2fliquid-haskell-cyclic-type-alias-definition-error-from-an-inlined-recursive-f%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

Refactoring coordinates for Minecraft Pi buildings written in Python