Liquid Haskell: “Cyclic type alias definition” error from an inlined recursive function
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
add a comment |
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
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 usereflect
, 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 useNewProofCombinators
rather thanProofCombinators
.
– Alex Varga
Nov 30 '18 at 17:40
add a comment |
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
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
haskell refinement-type liquid-haskell
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 usereflect
, 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 useNewProofCombinators
rather thanProofCombinators
.
– Alex Varga
Nov 30 '18 at 17:40
add a comment |
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 usereflect
, 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 useNewProofCombinators
rather thanProofCombinators
.
– 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
add a comment |
1 Answer
1
active
oldest
votes
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!
Thanks for you thorough answer Peter! I had figured out the need to usereflect
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 declaretype LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }
, how can I actually declare something likeone :: LT5
without an error? Even if I proveordLT 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 theLanguage.Haskell.Liquid.ProofCombinators
module, which are designed for dealing with this kind of thing. e.g. something likeone = 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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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!
Thanks for you thorough answer Peter! I had figured out the need to usereflect
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 declaretype LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }
, how can I actually declare something likeone :: LT5
without an error? Even if I proveordLT 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 theLanguage.Haskell.Liquid.ProofCombinators
module, which are designed for dealing with this kind of thing. e.g. something likeone = 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
add a comment |
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!
Thanks for you thorough answer Peter! I had figured out the need to usereflect
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 declaretype LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }
, how can I actually declare something likeone :: LT5
without an error? Even if I proveordLT 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 theLanguage.Haskell.Liquid.ProofCombinators
module, which are designed for dealing with this kind of thing. e.g. something likeone = 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
add a comment |
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!
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!
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 usereflect
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 declaretype LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }
, how can I actually declare something likeone :: LT5
without an error? Even if I proveordLT 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 theLanguage.Haskell.Liquid.ProofCombinators
module, which are designed for dealing with this kind of thing. e.g. something likeone = 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
add a comment |
Thanks for you thorough answer Peter! I had figured out the need to usereflect
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 declaretype LT5 = {v:Ordinal | ordLT v (Ord Zero 5 Zero) }
, how can I actually declare something likeone :: LT5
without an error? Even if I proveordLT 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 theLanguage.Haskell.Liquid.ProofCombinators
module, which are designed for dealing with this kind of thing. e.g. something likeone = 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 thanProofCombinators
.– Alex Varga
Nov 30 '18 at 17:40