compilation error when trying to define a new python like pow operator - idris

I want to mimic the Python's infix operator ** in Idris2:
(**) : Double -> Double -> Double
(**) x y = pow x y
But I'm getting this error:
Error: Couldn't parse declaration.
What am I doing wrong?

Related

Trying to bring implicit argument into scope on the left side of a definition in Idris results in "is f applied to too many arguments" error

The function applyRule is supposed to extract the implicit argument n that is used in another arguments it gets, of type VVect.
data IVect : Vect n ix -> (ix -> Type) -> Type where -- n is here
Nil : IVect Nil b
(::) : b i -> IVect is b -> IVect (i :: is) b
VVect : Vect n Nat -> Type -> Type -- also here
VVect is a = IVect is (flip Vect a)
-- just for completeness
data Expression = Sigma Nat Expression
applyRule : (signals : VVect is Double) ->
(params : List Double) ->
(sigmas : List Double) ->
(rule : Expression) ->
Double
applyRule {n} signals params sigmas (Sigma k expr1) = cast n
Without referring to {n}, the code type-checks (if cast n is changed to some valid double). Adding it in, however, results in the following error:
When checking left hand side of applyRule:
Type mismatch between
Double (Type of applyRule signals params sigmas rule)
and
_ -> _ (Is applyRule signals
params
sigmas
rule applied to too many arguments?)
This doesn't seem to make sense to me, because I'm not pattern-matching on any parameter that could have a dependency on n, so I thought that simply putting it in curly braces would bring it into scope.
You can only bring n into scope if it is defined somewhere (e.g. as a variable in the arguments). Otherwise it would be hard to figure out where the n comes from – at least for a human.
applyRule : {is : Vect n Nat} ->
(signals : VVect is Double) ->
(params : List Double) ->
(sigmas : List Double) ->
(rule : Expression) ->
Double
applyRule {n} signals params sigmas (Sigma k expr1) = cast n

Haskell: Scope of a variable

I am creating a function that given a list of Char, gives the same list but only with the numbers:
algarismos :: [Char] -> [Char]
algarismos [] = []
algarismos (x:xs) | (isDigit x) =x:(algarismos xs)
| otherwise =(algarismos xs)
I get the error message
error: Variable not in scope: isDigit :: Char -> Bool
Why does it say isDigit doesn't have variable in scope if the x is there?
As long as you're giving us all your code, this is the actual error message:
error: Variable not in scope: isDigit :: Char -> Bool
This is saying that isDigit isn't defined, not anything else.
You need to import Data.Char, which contains isDigit. Put this at the top of your file:
import Data.Char (isDigit)
This imports the function isDigit from the base module Data.Char.
In the future, look for the imports you need to make using hoogle.

Can I write a generic function-wrapping function for a Wrapper interface representing a type that wraps some other type?

The full code example below (which successfully compiles) is a simplified and slightly contrived example of my problem.
NatPair is a pair of Nats, and I want to "lift" the binaryNum operations to NatPair pointwise, using the function lift_binary_op_to_pair.
But I can't implement Num NatPair because NatPair is not a data constructor.
So, I wrap it in a type WrappedNatPair, and I can provide a Num implementation for that type, with corresponding 'lifted' versions of + and *.
Then I want to generalise the idea of a wrapper type, with my Wrapper interface.
The function lift_natpair_bin_op_to_wrapped can lift a binary operation from NatPair
to WrappedNatPair, and the implementation code is entirely in terms of the unwrap and
wrap Wrapper interface methods.
But, if I try to generalise to
lift_bin_op_to_wrapped : Wrapper t => BinaryOp WrappedType -> BinaryOp t
then the type signature won't even compile, with error:
`-- Wrapping.idr line 72 col 23:
When checking type of Main.lift_bin_op_to_wrapped:
Can't find implementation for Wrapper t
(where the error location is the location of ':' in the type signature).
I think the problem is that t doesn't appear anywhere in the
type signature for the Wrapper interface WrapperType method,
so WrapperType can't be invoked anywhere other than inside
the interface definition itself.
(The workaround is to write boilerplate lift_<wrapped>_bin_op_to_<wrapper> methods with the same implementation code op x y = wrap $ op (unwrap x) (unwrap y) each time, which is not intolerable. But I would like to have a clear understanding of why I can't write the generic lift_bin_op_to_wrapped method.)
The full code which successfully compiles:
%default total
PairedType : (t : Type) -> Type
PairedType t = (t, t)
NatPair : Type
NatPair = PairedType Nat
data WrappedNatPair : Type where
MkWrappedNatPair : NatPair -> WrappedNatPair
equal_pair : t -> PairedType t
equal_pair x = (x, x)
BinaryOp : Type -> Type
BinaryOp t = t -> t -> t
lift_binary_op_to_pair : BinaryOp t -> BinaryOp (PairedType t)
lift_binary_op_to_pair op (x1, x2) (y1, y2) = (op x1 y1, op x2 y2)
interface Wrapper t where
WrappedType : Type
wrap : WrappedType -> t
unwrap : t -> WrappedType
Wrapper WrappedNatPair where
WrappedType = NatPair
wrap x = MkWrappedNatPair x
unwrap (MkWrappedNatPair x) = x
lift_natpair_bin_op_to_wrapped : BinaryOp NatPair -> BinaryOp WrappedNatPair
lift_natpair_bin_op_to_wrapped op x y = wrap $ op (unwrap x) (unwrap y)
Num WrappedNatPair where
(+) = lift_natpair_bin_op_to_wrapped (lift_binary_op_to_pair (+))
(*) = lift_natpair_bin_op_to_wrapped (lift_binary_op_to_pair (*))
fromInteger x = wrap $ equal_pair (fromInteger x)
WrappedNatPair_example : the WrappedNatPair 8 = (the WrappedNatPair 2) + (the WrappedNatPair 6)
WrappedNatPair_example = Refl
(Platform: Ubuntu 16.04 running Idris 1.1.1-git:83b1bed.)
I think the problem is that t doesn't appear anywhere in the type signature for the Wrapper interface WrapperType method, so WrapperType can't be invoked anywhere other than inside the interface definition itself.
You're right here. This is why you receive this error. You can fix this compilation error by explicitly specifying which types is wrapper like this:
lift_bin_op_to_wrapped : Wrapper w => BinaryOp (WrappedType {t=w}) -> BinaryOp w
lift_bin_op_to_wrapped {w} op x y = ?hole
But this probably won't help you because Idris somehow cannot deduce correspondence between w and WrappedType. I would love to see explanation of this fact. Basically compiler (I'm using Idris 1.0) says me next things:
- + Wrap.hole [P]
`-- w : Type
x : w
y : w
constraint : Wrapper w
op : BinaryOp WrappedType
-----------------------------------
Wrap.hole : w
Your WrappedType dependently typed interface method implements pattern matching on types in some tricky way. I think this might be a reason why you have problems. If you're familiar with Haskell you might see some similarities between your WrappedType and -XTypeFamilies. See this question:
Pattern matching on Type in Idris
Though you still can implement general wrapper function. You only need to desing your interface differently. I'm using trick described in this question: Constraining a function argument in an interface
interface Wraps (from : Type) (to : Type) | to where
wrap : from -> to
unwrap : to -> from
Wraps NatPair WrappedNatPair where
wrap = MkWrappedNatPair
unwrap (MkWrappedNatPair x) = x
lift_bin_op_to_wrapped : Wraps from to => BinaryOp from -> BinaryOp to
lift_bin_op_to_wrapped op x y = wrap $ op (unwrap x) (unwrap y)
Num WrappedNatPair where
(+) = lift_bin_op_to_wrapped (lift_binary_op_to_pair {t=Nat} (+))
(*) = lift_bin_op_to_wrapped (lift_binary_op_to_pair {t=Nat}(*))
fromInteger = wrap . equal_pair {t=Nat} . fromInteger
This compiles and works perfectly.

Evaluating `IO` Actions from REPL

Given:
*lecture2> :let x = (the (IO Int) (pure 42))
Looking at its type, what's the meaning of the MkFFI C_Types String String signature?
*lecture2> :t x
x : IO' (MkFFI C_Types String String) Int
I then attempted to evaluate x from the REPL:
*lecture2> :exec x
main:When checking argument value to function Prelude.Basics.the:
Type mismatch between
IO Int (Type of x)
and
Integer (Expected type)
Also, why doesn't 42 print out in the REPL?
Looking at its type, what's the meaning of the MkFFI C_Types String String signature?
The IO' type constructor is parametrised over the FFI that is available within it. It'll be different depending on e.g. the backend you want to target. Here you have access to the C FFI which is the default one IO picks.
You can find out about these things by using :doc in the REPL. E.g. :doc IO' yields:
Data type IO' : (lang : FFI) -> Type -> Type
The IO type, parameterised over the FFI that is available within it.
Constructors:
MkIO : (World -> PrimIO (WorldRes a)) -> IO' lang a
Also, why doesn't 42 print out in the REPL?
I don't know how :exec x is supposed to work but you can evaluate x in an interpreter by using :x x instead and that does yield a sensible output:
Idris> :x x
MkIO (\w => prim_io_pure 42) : IO' (MkFFI C_Types String String) Int

GHC rejects ST monad code as unable to unify type variables?

I wrote the following function:
(.>=.) :: Num a => STRef s a -> a -> Bool
r .>=. x = runST $ do
v <- readSTRef r
return $ v >= x
but when I tried to compile I got the following error:
Could not deduce (s ~ s1)
from the context (Num a)
bound by the type signature for
.>=. :: Num a => STRef s a -> a -> Bool
at test.hs:(27,1)-(29,16)
`s' is a rigid type variable bound by
the type signature for .>=. :: Num a => STRef s a -> a -> Bool
at test.hs:27:1
`s1' is a rigid type variable bound by
a type expected by the context: ST s1 Bool at test.hs:27:12
Expected type: STRef s1 a
Actual type: STRef s a
In the first argument of `readSTRef', namely `r'
In a stmt of a 'do' expression: v <- readSTRef r
Can anyone help?
This is exactly as intended. An STRef is only valid in one run of runST. And you try to put an external STRef into a new run of runST. That is not valid. That would allow arbitrary side-effects in pure code.
So, what you try is impossible to achieve. By design!
You need to stay within the ST context:
(.>=.) :: Ord a => STRef s a -> a -> ST s Bool
r .>=. x = do
v <- readSTRef r
return $ v >= x
(And as hammar points out, to use >= you need the Ord typeclass, which Num doesn't provide.)