so far, we have learnt the data keyword, and we can also learned how to create types synonyms with the type keywrod. (do not confuse that with the class keyword)
we'll be taking a look at how to make new types out of existing data types by using the newtype keyword and why we'd want to do that in the first place.
remember that we have said that we have examined the zipList, and let''s see how we will implements the zipList methods.
data ZipList a = ZipList [a]
but we will like to name a field called getZipList, here is new
data ZipList a = ZipList { getZipList :: [a] }
This looks fine and would actually work pretty well. We had two ways of making an existing type an instance of a type class, so we used the data keyword to just wrap that type into another type and made the other type an instance in the second way.
The newtype keyword in Haskell is made exactly for these cases when we want to just take one type and wrap it in something to present it as another type. In the actual libraries, ZipList a is defined like this:
and the zipList with the ZipList definition is like this:
newtype ZipList a = ZipList { getZipList :: [a] }
well, not too much difference except that the keyword has been changed from "data" to "newtype"? huh??
Instead of the data keyword, the newtype keyword is used. Now why is that? Well for one, newtype is faster. If you use the datakeyword to wrap a type, there's some overhead to all that wrapping and unwrapping when your program is running. But if you use newtype, Haskell knows that you're just using it to wrap an existing type into a new type (hence the name), because you want it to be the same internally but have a different type. With that in mind, Haskell can get rid of the wrapping and unwrapping once it resolves which value is of what type.
well, why not to use newtype all the time?
for 1, newtype ,is restricted to only one constructor with one field.
for 2, you cannot make data types that have several value constructors and each has zero or more fields , such as enum types as
data Profession = Fighter | Archer | Accountant
like data types, the newtype types can also do deriving.
suppose that we make a newtype "CharList"
newtype CharList = CharList { getCharList :: [Char] } deriving (Eq, Show)
so, the constructor type is something like this:
CharList :: [Char] -> CharList
and the field has the type, conversely as this
getCharList :: CharList -> [Char]
Now, suppose that we will make a newtype, which is called Pair, which is like a tuple, but because we cannot just use Maybe on a tuple and fmap on the first parameter, we get around this by definig the afore-mentioned pair.
newtype Pair b a = Pair { getPair :: (a,b) }
the following will show hte full code that does the type definition, instance implementation, and others.
-- file -- newtype_pair.hs -- description: -- with newtype define a pair class which allows us to fmap on the first -- parameter of a pair import Control.Applicative newtype Pair a b = Pair { getPair :: (a, b) } instance Functor (Pair c) where fmap f (Pair (x, y)) = Pair (f x, y) -- run it you can see the following -- ghci> getPair $ fmap (*100) (Pair (2,3)) -- (200,3) -- ghci> getPair $ fmap reverse (Pair ("london calling", 3)) -- ("gnillac nodnol",3)
We mentioned there is "for 1" on why to choose "newtype" over "data" when it is allowed. the second reason of "newtype" being advantage to "data" is that it is Lazy.
Lazy
Haskell being lazy, you heard it, right? so, what does lazy mean here? let's first examine the "undefined" value.
if you run the following on the ghci command line, you will get an exception.
ghci> undefined *** Exception: Prelude.undefined
But, you won't get any exception when you are running this.
ghci> head [3,4,5,undefined,2,undefined] 3
because the later won't be examine (and it is not necessary to examine ).
this is one of the live example of the lazyness, but we can go further and see lazyness in other situation.
suppose that we can define some bool like type, and it is now with the data definition.
data CoolBool = CoolBool { getCoolBool :: Bool }
and we define a function called heloMe, which disregard the value contained in CoolBool, and print Hello as always.
helloMe :: CoolBool -> String helloMe (CoolBool _) = "hello"
and now will throw a curveball (some unexpected situation) to it and see how it react. here it is.
ghci> helloMe undefined "*** Exception: Prelude.undefined
ah, it throws an exception , that is because data declared types can possibly have more than one constructor, and it has to go through evaluating the values before it can tell which will be applied, and the trivial evaluation that gives it away.
Let's now avert to the use the newtype declaration.
newtype CoolBool = CoolBool { getCoolBool :: Bool }
and we run it again with the following code.
ghci> helloMe undefined "hello"
why ????
the reason is that Haskell knows that types made with the newtype keyword can only have one constructor, it doesn't have to evaluate the value passed to the function to make sure that it conforms to the (CoolBool _) pattern because newtype types can only have one possible value constructor and one field!
so the rule of thumb. Whereas data can be used to make your own types from scratch, newtype is for making a completely new type out of an existing type. Pattern matching on newtype values isn't like taking something out of a box (like it is with data), it's more about making a direct conversion from one type to another.
相关推荐
Atom-haskell-ghc-mod.zip,haskell-ghc-mod atom packagehaskell ghc mod atom包,atom是一个用web技术构建的开源文本编辑器。
haskell-mode emacs haskell-mode emacs
Atom-ide-haskell-hoogle.zip,在光标下显示符号的滚动信息艾德·哈斯克尔·胡格尔,atom是一个用web技术构建的开源文本编辑器。
Haskell-Data-Analysis-Cookbook, Haskell数据分析 cookbook的附带源代码 Haskell-Data-Analysis-Cookbook这是 Haskell数据分析 cookbook的附带源代码。最新的源代码可以在GitHub上获得: ...
从1.0.0开始,haskell-ghc-mod提供haskell-completion-backend服务。 注意:在1.0.0之前,提供了ide-backend服务。 它已被废弃以支持ide-haskell的UPI。 您可以在找到描述 执照 版权所有:copyright:2015 Atom-...
Programming-in-Haskell-2nd-Edition.pdf
haskell-ghc-mod原子包 该软件包主要用作后端。 Haskell ghc-mod打开通往ghc-modi的管道,并查询类型,信息并检查错误。 安装与配置 请参考官方文档站点 服务中心API 从1.0.0版本开始,haskell-ghc-mod提供...
Get Programming with HASKELL-2018-英文版
用于 haskell-relational-record 的 MySQL 驱动程序 这个项目被合并到 。 准备 $ git clone git@github.com:khibino/haskell-relational-record.git $ git clone git@github.com:bos/hdbc-mysql.git $ git clone ...
演示医疗用例的参考DAML应用程序 -Haskell-TypeScript-下载
haskell-chart, haskell的2D 图表库 图 haskell的2D 图表库进一步的信息可以在关联的 wiki中找到。
Server Metaprogramming Ruby-Pyton-Groovy-Haskell-Erlang.pdf
A History of Haskell - Being Lazy With Class
Atom-ide-haskell-cabal.zip,Cabal backend provider for ide-haskellIDE Haskell Cabal套餐,atom是一个用web技术构建的开源文本编辑器。
你可以在找到 haskell-brainfuck用法图书馆 import HaskBF.Evalimport qualified Data.ByteString.Lazy as BSimport Control.Monad.Statemain = do -- The following will evaluate the file using stdin and ...
haskell-lsp-client 该软件包适用于希望使其文本编辑器与兼容的文本编辑器的开发人员。 我已经开发了此软件包,并计划将其集成到。 示例客户端 该存储库中包含一个示例客户端。 此示例客户端仅运行并打开在命令行...
Atom-atom-haskell-scry.zip,De-emphasize qualified Haskell identifiers.SCRY,atom是一个用web技术构建的开源文本编辑器。
Atom-atom-haskell-pointfree.zip,atom包:将选择转换为无点或有点表示Haskell无点包,atom是一个用web技术构建的开源文本编辑器。
Haskell - The Craft of Functional Programming, 2ed (Addison-Wesley, 1999) by Tantanoid 已加书签
Atom-haskell-debug.zip,使用ghci在atom中实现图形haskell调试器Haskell调试,atom是一个用web技术构建的开源文本编辑器。