How can I find the definition of a Prelude function? - haskell

I'm currently trying to find the definition of the words function to help get an idea for a similar function I'm writing. So I was wondering is there somewhere that has all the definitions of the Prelude functions? Maybe a GHCi command to show the definition of one, or something on the Haskell wiki, I'm not sure.
Or if there isn't somewhere I can find that do any of y'all know what the definitions of words is?

Most packages on Hackage come with documentation that also includes a link to the source code for every function. You can usually find the function via Hoogle.
In the case of words, the Prelude documentation is found here, and the source is found at https://hackage.haskell.org/package/base-4.16.3.0/docs/src/Data.OldList.html#words:
-- | 'words' breaks a string up into a list of words, which were delimited
-- by white space.
--
-- >>> words "Lorem ipsum\ndolor"
-- ["Lorem","ipsum","dolor"]
words :: String -> [String]
{-# NOINLINE [1] words #-}
words s = case dropWhile {-partain:Char.-}isSpace s of
"" -> []
s' -> w : words s''
where (w, s'') =
break {-partain:Char.-}isSpace s'
This should in general also work with local documentation.
For ghci specifically, there are :info and :list commands, but :list words only produces an error message ("cannot list source code for words: module base-…:Data.OldList is not interpreted") for me.

Documentation of a function.
To search for the definition, look at hackage. In the case of words: https://hackage.haskell.org/package/base-4.16.3.0/docs/Prelude.html#v:words
Finding a function
To find a function, use hoogle. It is the de-facto tool for finding a function.
Example:
This is inside the shell. Hoogle can be installed at the samne time as when ghc is.
Find a function like so:
> hoogle "subtract"
Prelude subtract :: Num a => a -> a -> a
GHC.Num subtract :: Num a => a -> a -> a
Distribution.Compat.Prelude.Internal subtract :: Num a => a -> a -> a
GHC.Prelude subtract :: Num a => a -> a -> a
Hedgehog.Internal.Prelude subtract :: Num a => a -> a -> a
BasePrelude subtract :: Num a => a -> a -> a
RIO.Prelude subtract :: Num a => a -> a -> a
System.Metrics.Gauge subtract :: Gauge -> Int64 -> IO ()
ClassyPrelude subtract :: Num a => a -> a -> a
Algebra.Additive subtract :: C a => a -> a -> a
-- plus more results not shown, pass --count=20 to see more
The cool thing is, you can also search for types and functions with certain types. For example, here is the list of functions which will take an Int and return an Int.
hoogle "Int -> Int"
GHC.Unicode wgencat :: Int -> Int
System.Win32.DebugApi dr :: Int -> Int
Codec.Picture.Jpg.Internal.Common toBlockSize :: Int -> Int
Statistics.Function nextHighestPowerOfTwo :: Int -> Int
Numeric.SpecFunctions log2 :: Int -> Int
Math.NumberTheory.Logarithms intLog2 :: Int -> Int
Math.NumberTheory.Logarithms intLog2' :: Int -> Int
Streamly.Internal.Data.Array.Foreign.Mut.Type roundUpToPower2 :: Int -> Int
Streamly.Internal.System.IO arrayPayloadSize :: Int -> Int
Data.Array.Comfort.Shape triangleSize :: Int -> Int
-- plus more results not shown, pass --count=20 to see more

Related

Strict type alias in Haskell

Suppose I have a recursive function taking 3 integers, each having a different meaning, e.g.
func :: Int -> Int -> Int -> SomeType1 -> SomeType2
What I want is to prevent myself from mistyping the order of the arguments like this (somewhere in the func implementation):
func a b c t = f b a c ( someProcessing t )
The easiest way I've come up with is to define type aliases like
type FuncFirstArg = Int
type FuncSecondArg = Int
type FuncThirdArg = Int
And change func signature:
func :: FuncFirstArg -> FuncSecondArg -> FuncThirdArg -> SomeType1 -> SomeType2
But it seems like this approach doesn't work as I intended. Why does Haskell still allow me to pass FuncSecondArg as a first argument and so on. Is there a way to do what I want without declaring datatypes?
type in Haskell is a rename of an existing type. Just like String and [Char] are fully exchangeable, so are FuncFirstArg and Int, and by transition FuncSecondArg as well.
The most normal solution is to use a newtype which was introduced exactly for the purpose of what you try to achieve. For convenience, it is good to declare it as a record:
newtype FuncFirstArg = FuncFirstArg {unFuncFirstArg :: Int}
Note that newtype is entirely reduced during compilation time, so it has no overhead on the runtime.
However, if you have many arguments like in your example, a common strategy is to create a dedicated type for all of the parameters supplied to the function:
data FuncArgs = FuncArgs
{ funcA :: Int
, funcB :: Int
, funcC :: Int
, funcT :: Sometype1
}
f :: FuncArgs -> Sometype2
Yes, it has some bad impact on currying and partial application, but in many cases you can deal with it by providing predefined argument packs or even uncurry the function:
defaultArgs :: Sometype1 -> FuncArgs
defaultArgs t = FuncArgs {a = 0, b = 0, c = 0, t = t}
fUnc :: Int -> Int -> Int -> SomeType1 -> SomeType2
fUnc a b c t = f $ FuncArgs a b c t
Conclusion
For the typechecker to distinguish types, the types have to be actually different. You can't skip defining new types, therefore.

Trouble understanding types in Haskell

I'm given the following where:
data Card = Card Suit Rank
deriving (Eq, Ord, Show)
type BidFunc
= Card -- ^ trump card
-> [Card] -- ^ list of cards in the player's hand
-> Int -- ^ number of players
-> [Int] -- ^ bids so far
-> Int -- ^ the number of tricks the player intends to win
where I'm required to write a function of
makeBid :: BidFunc
makeBid = (write here)
The problem I'm having is that i couldnt understand the syntax of the function type declared which is BidFunc. I'm new to Haskell so i would appreciate if someone could give me an explanation clear enough on the function type above.
In particularly, why is there a '=' Card, followed by -> [Card] etc? Am i supposed to pass in arguments to the function type?
makeBid :: BidFunc is exactly the same as makeBid :: Car -> [Card] -> Int -> [Int] -> Int, so you would define the function in exactly the same way:
makeBid :: BidFunc
-- makeBid :: Card -> [Card] -> Int -> [Int] -> Int
makeBid c cs n bs = ...
As for the formatting of the type definition, it's just that: formatting. IMO, it would be a little clearer written as
type BidFunc = Card -- ...
-> [Card] -- ...
-> Int -- ...
-> [Int] -- ...
-> Int -- ...
if you want to comment on each argument and the return value. Without comments, it can of course be written on one line:
type BidFunc = Card -> [Card] -> Int -> [Int] -> Int
In general, type <lhs> = <rhs> just remeans that <lhs> is a name that can refer to whatever type <rhs> specifies.
As to why one might feel the need to define a type alias for something that isn't going to be reused often, I couldn't say. Are they any other functions beside makeBid that would have the same type?

Haskell type declarations

In Haskell, why does this compile:
splice :: String -> String -> String
splice a b = a ++ b
main = print (splice "hi" "ya")
but this does not:
splice :: (String a) => a -> a -> a
splice a b = a ++ b
main = print (splice "hi" "ya")
>> Type constructor `String' used as a class
I would have thought these were the same thing. Is there a way to use the second style, which avoids repeating the type name 3 times?
The => syntax in types is for typeclasses.
When you say f :: (Something a) => a, you aren't saying that a is a Something, you're saying that it is a type "in the group of" Something types.
For example, Num is a typeclass, which includes such types as Int and Float.
Still, there is no type Num, so I can't say
f :: Num -> Num
f x = x + 5
However, I could either say
f :: Int -> Int
f x = x + 5
or
f :: (Num a) => a -> a
f x = x + 5
Actually, it is possible:
Prelude> :set -XTypeFamilies
Prelude> let splice :: (a~String) => a->a->a; splice a b = a++b
Prelude> :t splice
splice :: String -> String -> String
This uses the equational constraint ~. But I'd avoid that, it's not really much shorter than simply writing String -> String -> String, rather harder to understand, and more difficult for the compiler to resolve.
Is there a way to use the second style, which avoids repeating the type name 3 times?
For simplifying type signatures, you may use type synonyms. For example you could write
type S = String
splice :: S -> S -> S
or something like
type BinOp a = a -> a -> a
splice :: BinOp String
however, for something as simple as String -> String -> String, I recommend just typing it out. Type synonyms should be used to make type signatures more readable, not less.
In this particular case, you could also generalize your type signature to
splice :: [a] -> [a] -> [a]
since it doesn't depend on the elements being characters at all.
Well... String is a type, and you were trying to use it as a class.
If you want an example of a polymorphic version of your splice function, try:
import Data.Monoid
splice :: Monoid a=> a -> a -> a
splice = mappend
EDIT: so the syntax here is that Uppercase words appearing left of => are type classes constraining variables that appear to the right of =>. All the Uppercase words to the right are names of types
You might find explanations in this Learn You a Haskell chapter handy.

How to declare function (type misunderstanding Maybe)

I need a function which works like:
some :: (Int, Maybe Int) -> Int
some a b
| b == Nothing = 0
| otherwise = a + b
Use cases:
some (2,Just 1)
some (3,Nothing)
map some [(2, Just 1), (3,Nothing)]
But my code raise the error:
The equation(s) for `some' have two arguments,
but its type `(Int, Maybe Int) -> Int' has only one
I don't understand it.
Thanks in advance.
When you write
foo x y = ...
That is notation for a curried function, with a type like:
foo :: a -> b -> c
You have declared your function to expect a tuple, so you must write it:
some :: (Int, Maybe Int) -> Int
some (x, y) = ...
But Haskell convention is usually to take arguments in the former curried form. Seeing funcitons take tuples as arguments is very rare.
For the other part of your question, you probably want to express it with pattern matching. You could say:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x + 1
Generalizing that to the OP's question is left as an exercise for the reader.
Your error doesn't come from a misunderstanding of Maybe: The type signature of some indicates that it takes a pair (Int, Maybe Int), while in your definition you provide it two arguments. The definition should thus begin with some (a,b) to match the type signature.
One way to fix the problem (which is also a bit more idiomatic and uses pattern matching) is:
some :: (Int, Maybe Int) -> Int
some (a, Nothing) = a
some (a, Just b) = a + b
It's also worth noting that unless you have a really good reason for using a tuple as input, you should probably not do so. If your signature were instead some :: Int -> Maybe Int -> Int, you'd have a function of two arguments, which can be curried. Then you'd write something like
some :: Int -> Maybe Int -> Int
some a Nothing = a
some a (Just b) = a + b
Also, you might want to add the following immediate generalization: All Num types are additive, so you might aswell do
some :: (Num n) => n -> Maybe n -> n
some a Nothing = a
some a (Just b) = a + b
(I've violated the common practice of using a, b, c... for type variables so as not to confuse the OP since he binds a and b to the arguments of some).

What to do with “Inferred type is less polymorphic than expected”?

I need the Numeric.FAD library, albeit still being completely puzzled by existential types.
This is the code:
error_diffs :: [Double] -> NetworkState [(Int, Int, Double)]
error_diffs desired_outputs = do diff_error <- (diff_op $ error' $ map FAD.lift desired_outputs)::(NetworkState ([FAD.Dual tag Double] -> FAD.Dual tag Double))
weights <- link_weights
let diffs = FAD.grad (diff_error::([FAD.Dual tag a] -> FAD.Dual tag b)) weights
links <- link_list
return $ zipWith (\link diff ->
(linkFrom link, linkTo link, diff)
) links diffs
error' runs in a Reader monad, ran by diff_op, which in turn generates an anonymous function to take the current NetworkState and the differential inputs from FAD.grad and stuffs them into the Reader.
Haskell confuses me with the following:
Inferred type is less polymorphic than expected
Quantified type variable `tag' is mentioned in the environment:
diff_error :: [FAD.Dual tag Double] -> FAD.Dual tag Double
(bound at Operations.hs:100:33)
In the first argument of `FAD.grad', namely
`(diff_error :: [FAD.Dual tag a] -> FAD.Dual tag b)'
In the expression:
FAD.grad (diff_error :: [FAD.Dual tag a] -> FAD.Dual tag b) weights
In the definition of `diffs':
diffs = FAD.grad
(diff_error :: [FAD.Dual tag a] -> FAD.Dual tag b) weights
this code gives the same error as you get:
test :: Int
test =
(res :: Num a => a)
where
res = 5
The compiler figured that res is always of type Int and is bothered that for some reason you think res is polymorphic.
this code, however, works fine:
test :: Int
test =
res
where
res :: Num a => a
res = 5
here too, res is defined as polymorphic but only ever used as Int. the compiler is only bothered when you type nested expressions this way. in this case res could be reused and maybe one of those uses will not use it as Int, in contrast to when you type a nested expression, which cannot be reused by itself.
If I write,
bigNumber :: (Num a) => a
bigNumber = product [1..100]
then when bigNumber :: Int is evaluated,
it's evaluating (product :: [Int] -> Int) [(1 :: Int) .. (100 :: Int)],
and when bigNumber :: Integer is evaluated,
it's evaluating (product :: [Integer] -> Integer) [(1 :: Integer) .. (100 :: Integer)].
Nothing is shared between the two.
error_diffs has a single type, that is: [Double] -> NetworkState [(Int, Int, Double)]. It must evaluate in exactly one way.
However, what you have inside:
... :: NetworkState ([FAD.Dual tag Double] -> FAD.Dual tag Double)
can be evaluated in different ways, depending on what tag is.
See the problem?

Resources