在Haskell中是否可以定义类似于ziplist的类型,其中操作a <*> b
将生成与a
和{{的最长一样长的列表1}}。
很明显,在这种情况下,我们必须假设b
和a
是类似Monoid的列表,所以暂定声明是:
b
显然不会进行类型检查。另一种尝试性方法是使用具有约束构造函数的GADT,类似于
instance Monoid a => Applicative (ZList a) where ...
但后来我陷入了使其成为Functor的阶段,因为我们不能保证在 data ZList a where
Z:: ZList a
S:: Monoid a => a-> (ZList a) -> (ZList a)
中,b将是Monoid。
显然,这个问题延伸到更广泛的代数数据类型,我们想要定义这些数据类型&#34;逐点&#34;我们生成的输出形式类似于参数形状的 union 的应用行为。
答案 0 :(得分:2)
首先,您真正想要的可能是Default
,而不是Monoid
- 您对mappend
毫无用处。
我认为Applicative
本身无法做出任何有用的事情。也就是说,我可以定义一个(<*>)
版本(称为(<#>)
),其中包含额外的约束,让我可以按照我的想法行事。
首先,假设我们 采取ExistentialQuantification
路线,希望将我们的约束推送到data
并拥有Functor
和{{的合法实例1}}。一旦我们尝试定义Applicative
:
fmap
所以,在结算的情况下,让我们坚持使用{-# LANGUAGE ExistentialQuantification #-}
data ZipMonList a = Default a => ZipMonList [a]
-- Woops, we still need a constraint for `Default b`
fmap :: Default b => (a -> b) -> ZipMonList a -> ZipMonList b
fmap f (ZipMonList xs) = ZipMonList (f xs)
类型(因为我们想要相同的ZipList
)并且只定义(<$>)
的新约束版本,叫(<*>)
。
(<#>)
(<#>)
基础ZipList
s ZipList
是(<*>)
功能。我们需要zipWith
类似的东西,但这会扩展列表。然后,(<#>)
看起来很像(<#>)
:
(<*>)
我可以对元组进行测试:
import Control.Applicative (ZipList(..))
import Data.Default
-- Like 'zipWith', but has maximum length
zipWith' :: (Default a, Default b) => (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f [] [] = []
zipWith' f (x:xs) [] = f x def : zipWith' f xs []
zipWith' f [] (y:ys) = f def y : zipWith' f [] ys
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
-- same fixity as <*>
infixl 4 <#>
-- like '(<*>)', but uses 'zipWith'' instead of 'zipWith'
(<#>) :: (Default a, Default b) => ZipList (a -> b) -> ZipList a -> ZipList b
ZipList fs <#> ZipList xs = ZipList (zipWith' id fs xs)
关键点:这是不 ghci> (,,) <$> ZipList [1.2,3.4,5.6,7.8,9.1] <#> ZipList [[(),()],[()],[(),(),()]] <#> ZipList [1,2,3,4]
ZipList {getZipList = [(1.2,[(),()],1),(3.4,[()],2),(5.6,[(),(),()],3),(7.8,[],4),(9.1,[],0)]}
,但仍然可行。
答案 1 :(得分:1)
我只想给你一些笔记,要考虑的事情。
允许这种情况的类型类的定义称为Constrained Typeclass Problem,并且有一些方法。
我注意到您只是指定结果列表应该与两个列表中的较长列表一样长,但您还没有说明其余元素应该是什么。那时你也可以使用适用的
whirlpool shop owner
(其中:*:
is functor product和public class Client extends Application{
String name, sname;
TextField userTextField = new TextField();
TextField fTextField = new TextField();
String recip;
TextFlow textFlow = new TextFlow();
ScrollPane sp = new ScrollPane();
Button button = new Button("Send");
int i=0;
public Parent content() {
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Text scenetitle = new Text("Welcome");
scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
grid.add(scenetitle, 0, 0, 2, 1);
Label userName = new Label("User Name:");
grid.add(userName, 0, 1);
grid.add(userTextField, 1, 1);
Label fName = new Label("Friend Name:");
grid.add(fName, 0, 2);
grid.add(fTextField, 1, 2);
Button button = new Button("Start");
DropShadow shadow = new DropShadow();
button.addEventHandler(MouseEvent.MOUSE_ENTERED, (MouseEvent e) -> {
button.setEffect(shadow);
});
button.addEventHandler(MouseEvent.MOUSE_EXITED, (MouseEvent e) -> {
button.setEffect(null);
});
button.setOnAction( e -> grid.getScene().getWindow().hide());
grid.add(button,1,6);
String name;
name = userTextField.getText();
System.out.println(name);
recip = fTextField.getText();
System.out.println(recip);
return grid;
}
public Parent createContent(){
textFlow.setPadding(new Insets(10));
textFlow.setLineSpacing(10);
TextField textField = new TextField();
textField.setPrefSize(300,30);
button.setPrefSize(80,30);
VBox container = new VBox();
VBox box = new VBox();
box.getChildren().addAll(sp,textFlow);
container.setPadding(new Insets(10));
container.getChildren().addAll(box, new HBox(textField, button));
VBox.setVgrow(sp, Priority.ALWAYS);
VBox.setVgrow(textFlow, Priority.ALWAYS);
return container;
}
public void start(Stage stage) throws IOException {
Parent q= content();
Scene scene = new Scene(q,300,400);
stage.setScene(scene);
stage.setTitle("Chit-Chat");
stage.show();
if (i == 1) {
VBox vb = new VBox();
vb.getChildren().addAll(textFlow);
sp.setVmax(440);
sp.setPrefSize(400, 300);
sp.setContent(vb);
sp.vvalueProperty().bind((ObservableValue<? extends Number>) vb.heightProperty());
Parent p = createContent();
Scene scene2 = new Scene(p, 400, 300);
stage.setScene(scene2);
stage.setTitle("Chit-Chat");
stage.show();
}
}
}
public static void main(String[] args) throws IOException {
launch(args);
}
}
是一个幺半群,我只是在非负数上取最大值),它跟踪了长度&#34;分开,因为剩下的元素将毫无意义。
相反,我怀疑你的意思是在某种意义上保留其余元素,即所以
ZipList :*: Const (MaxPos Int)
以及
MaxPos
所以,如果我们要填写&#34;在前一种情况下缺少元素我们应该用1填充它们,而在后者中我们应该用0填充它们。这开始向我们展示问题的不同方面;我们需要根据操作选择身份元素,或者只是单独留下&#34;其余元素(将操作限制为(*) <$> [2,3,4] <*> [4] = [8,3,4]
类型)。这看起来不太可能,探索更多内容会很有趣。这就是我现在所拥有的,抱歉。